diff options
Diffstat (limited to 'package/linux/kernel-patches')
-rw-r--r-- | package/linux/kernel-patches/000-linux-mips-cvs | 16298 | ||||
-rw-r--r-- | package/linux/kernel-patches/302-ebtables | 9475 |
2 files changed, 18612 insertions, 7161 deletions
diff --git a/package/linux/kernel-patches/000-linux-mips-cvs b/package/linux/kernel-patches/000-linux-mips-cvs index dbd23de973..8a4a7d6ae4 100644 --- a/package/linux/kernel-patches/000-linux-mips-cvs +++ b/package/linux/kernel-patches/000-linux-mips-cvs @@ -1,125 +1,298 @@ -diff -Nur linux-2.4.29/Makefile linux-mips/Makefile ---- linux-2.4.29/Makefile 2005-01-19 15:10:14.000000000 +0100 -+++ linux-mips/Makefile 2005-01-20 03:19:21.000000000 +0100 -@@ -5,7 +5,7 @@ - - KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) - --ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -+ARCH = mips - KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") - - CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ -@@ -462,10 +462,11 @@ - $(MAKE) -C Documentation/DocBook mrproper - - distclean: mrproper -- rm -f core `find . \( -not -type d \) -and \ -- \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -- -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -- -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags -+ find . \( -not -type d \) -and \ -+ \( -name core -o -name '*.orig' -o -name '*.rej' \ -+ -o -name '*~' -o -name '*.bak' -o -name '#*#' \ -+ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \ -+ -o -name TAGS -o -name tags \) -print | env -i xargs rm -f - - backup: mrproper - cd .. && tar cf - linux/ | gzip -9 > backup.gz -@@ -492,7 +493,7 @@ - $(MAKE) -C Documentation/DocBook man - - sums: -- find . -type f -print | sort | xargs sum > .SUMS -+ find . -type f -print | sort | env -i xargs sum > .SUMS - - dep-files: scripts/mkdep archdep include/linux/version.h - rm -f .depend .hdepend -diff -Nur linux-2.4.29/arch/mips/Makefile linux-mips/arch/mips/Makefile ---- linux-2.4.29/arch/mips/Makefile 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/Makefile 2005-01-31 12:59:28.000000000 +0100 -@@ -211,7 +211,7 @@ - endif - - # --# Au1000 (Alchemy Semi PB1000) eval board -+# Au1x AMD Alchemy eval boards - # - ifdef CONFIG_MIPS_PB1000 - LIBS += arch/mips/au1000/pb1000/pb1000.o \ -@@ -220,9 +220,6 @@ - LOADADDR := 0x80100000 - endif - --# --# Au1100 (Alchemy Semi PB1100) eval board --# - ifdef CONFIG_MIPS_PB1100 - LIBS += arch/mips/au1000/pb1100/pb1100.o \ - arch/mips/au1000/common/au1000.o -@@ -230,9 +227,6 @@ - LOADADDR += 0x80100000 - endif - --# --# Au1500 (Alchemy Semi PB1500) eval board --# - ifdef CONFIG_MIPS_PB1500 - LIBS += arch/mips/au1000/pb1500/pb1500.o \ - arch/mips/au1000/common/au1000.o -@@ -240,9 +234,6 @@ - LOADADDR := 0x80100000 - endif - --# --# Au1x00 (AMD/Alchemy) eval boards --# - ifdef CONFIG_MIPS_DB1000 - LIBS += arch/mips/au1000/db1x00/db1x00.o \ - arch/mips/au1000/common/au1000.o -@@ -313,6 +304,27 @@ - LOADADDR += 0x80100000 - endif +diff -Nur linux-2.4.29/arch/i386/kernel/acpi.c linux-mips/arch/i386/kernel/acpi.c +--- linux-2.4.29/arch/i386/kernel/acpi.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/arch/i386/kernel/acpi.c 2005-03-26 11:47:12.638577463 +0100 +@@ -55,6 +55,7 @@ + + acpi_interrupt_flags acpi_sci_flags __initdata; + int acpi_sci_override_gsi __initdata; ++int acpi_skip_timer_override __initdata; + /* -------------------------------------------------------------------------- + Boot-time Configuration + -------------------------------------------------------------------------- */ +@@ -320,6 +321,12 @@ + return 0; + } -+ifdef CONFIG_MIPS_PB1200 -+LIBS += arch/mips/au1000/pb1200/pb1200.o \ -+ arch/mips/au1000/common/au1000.o -+SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common -+LOADADDR += 0x80100000 -+endif -+ -+ifdef CONFIG_MIPS_DB1200 -+LIBS += arch/mips/au1000/pb1200/pb1200.o \ -+ arch/mips/au1000/common/au1000.o -+SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common -+LOADADDR += 0x80100000 -+endif -+ -+ifdef CONFIG_MIPS_FICMMP -+LIBS += arch/mips/au1000/ficmmp/ficmmp.o \ -+ arch/mips/au1000/common/au1000.o -+SUBDIRS += arch/mips/au1000/ficmmp arch/mips/au1000/common -+LOADADDR += 0x80100000 -+endif ++ if (acpi_skip_timer_override && ++ intsrc->bus_irq == 0 && intsrc->global_irq == 2) { ++ printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); ++ return 0; ++ } + + mp_override_legacy_irq ( + intsrc->bus_irq, + intsrc->flags.polarity, +@@ -433,6 +440,10 @@ + return result; + } - # - # Cogent CSB250 -diff -Nur linux-2.4.29/arch/mips/au1000/common/Makefile linux-mips/arch/mips/au1000/common/Makefile ---- linux-2.4.29/arch/mips/au1000/common/Makefile 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/common/Makefile 2005-01-31 12:59:30.000000000 +0100 -@@ -19,9 +19,9 @@ - export-objs = prom.o clocks.o power.o usbdev.o ++#ifdef CONFIG_X86_IOAPIC ++ check_acpi_pci(); ++#endif ++ + result = acpi_blacklisted(); + if (result) { + printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); +diff -Nur linux-2.4.29/arch/i386/kernel/earlyquirk.c linux-mips/arch/i386/kernel/earlyquirk.c +--- linux-2.4.29/arch/i386/kernel/earlyquirk.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-mips/arch/i386/kernel/earlyquirk.c 2005-03-18 13:13:20.000000000 +0100 +@@ -0,0 +1,53 @@ ++/* ++ * Do early PCI probing for bug detection when the main PCI subsystem is ++ * not up yet. ++ */ ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/pci.h> ++#include <asm/pci-direct.h> ++#include <asm/acpi.h> ++ ++#ifdef CONFIG_ACPI ++static int __init check_bridge(int vendor, int device) ++{ ++ /* According to Nvidia all timer overrides are bogus. Just ignore ++ them all. */ ++ if (vendor == PCI_VENDOR_ID_NVIDIA) { ++ acpi_skip_timer_override = 1; ++ } ++ return 0; ++} ++ ++void __init check_acpi_pci(void) ++{ ++ int num,slot,func; ++ ++ /* Assume the machine supports type 1. If not it will ++ always read ffffffff and should not have any side effect. */ ++ ++ /* Poor man's PCI discovery */ ++ for (num = 0; num < 32; num++) { ++ for (slot = 0; slot < 32; slot++) { ++ for (func = 0; func < 8; func++) { ++ u32 class; ++ u32 vendor; ++ class = read_pci_config(num,slot,func, ++ PCI_CLASS_REVISION); ++ if (class == 0xffffffff) ++ break; ++ ++ if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) ++ continue; ++ ++ vendor = read_pci_config(num, slot, func, ++ PCI_VENDOR_ID); ++ ++ if (check_bridge(vendor&0xffff, vendor >> 16)) ++ return; ++ } ++ ++ } ++ } ++} ++#endif /* CONFIG_ACPI */ +diff -Nur linux-2.4.29/arch/i386/kernel/Makefile linux-mips/arch/i386/kernel/Makefile +--- linux-2.4.29/arch/i386/kernel/Makefile 2003-11-28 19:26:19.000000000 +0100 ++++ linux-mips/arch/i386/kernel/Makefile 2005-03-26 11:47:12.567589113 +0100 +@@ -40,7 +40,7 @@ + obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o + obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o + obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o +-obj-$(CONFIG_X86_IO_APIC) += io_apic.o ++obj-$(CONFIG_X86_IO_APIC) += io_apic.o earlyquirk.o + obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o + obj-$(CONFIG_EDD) += edd.o + +diff -Nur linux-2.4.29/arch/i386/kernel/pci-irq.c linux-mips/arch/i386/kernel/pci-irq.c +--- linux-2.4.29/arch/i386/kernel/pci-irq.c 2005-01-19 15:09:25.000000000 +0100 ++++ linux-mips/arch/i386/kernel/pci-irq.c 2005-03-26 11:47:12.808549566 +0100 +@@ -1120,13 +1120,15 @@ + void pcibios_enable_irq(struct pci_dev *dev) + { + u8 pin; +- extern int interrupt_line_quirk; ++ extern int via_interrupt_line_quirk; + struct pci_dev *temp_dev; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { + char *msg; - obj-y := prom.o int-handler.o irq.o puts.o time.o reset.o cputable.o \ -- au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o -+ au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o gpio.o - --export-objs += dma.o dbdma.o -+export-objs += dma.o dbdma.o gpio.o ++ pin--; /* interrupt pins are numbered starting from 1 */ ++ + /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) + return; +@@ -1134,46 +1136,43 @@ + if (io_apic_assign_pci_irqs) { + int irq; + +- if (pin) { +- pin--; /* interrupt pins are numbered starting from 1 */ +- irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); +- /* +- * Busses behind bridges are typically not listed in the MP-table. +- * In this case we have to look up the IRQ based on the parent bus, +- * parent slot, and pin number. The SMP code detects such bridged +- * busses itself so we should get into this branch reliably. +- */ +- temp_dev = dev; +- while (irq < 0 && dev->bus->parent) { /* go back to the bridge */ +- struct pci_dev * bridge = dev->bus->self; ++ irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); ++ /* ++ * Busses behind bridges are typically not listed in the MP-table. ++ * In this case we have to look up the IRQ based on the parent bus, ++ * parent slot, and pin number. The SMP code detects such bridged ++ * busses itself so we should get into this branch reliably. ++ */ ++ temp_dev = dev; ++ while (irq < 0 && dev->bus->parent) { /* go back to the bridge */ ++ struct pci_dev * bridge = dev->bus->self; + +- pin = (pin + PCI_SLOT(dev->devfn)) % 4; +- irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, +- PCI_SLOT(bridge->devfn), pin); +- if (irq >= 0) +- printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", +- bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq); +- dev = bridge; +- } +- dev = temp_dev; +- if (irq >= 0) { +- printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", +- dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); +- dev->irq = irq; +- return; +- } else +- msg = " Probably buggy MP table."; ++ pin = (pin + PCI_SLOT(dev->devfn)) % 4; ++ irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, ++ PCI_SLOT(bridge->devfn), pin); ++ if (irq >= 0) ++ printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", ++ bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq); ++ dev = bridge; + } ++ dev = temp_dev; ++ if (irq >= 0) { ++ printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", ++ dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); ++ dev->irq = irq; ++ return; ++ } else ++ msg = " Probably buggy MP table."; + } else if (pci_probe & PCI_BIOS_IRQ_SCAN) + msg = ""; + else + msg = " Please try using pci=biosirq."; + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", +- 'A' + pin - 1, dev->slot_name, msg); ++ 'A' + pin, dev->slot_name, msg); + } + /* VIA bridges use interrupt line for apic/pci steering across + the V-Link */ +- else if (interrupt_line_quirk) ++ else if (via_interrupt_line_quirk) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15); + + } +diff -Nur linux-2.4.29/arch/i386/kernel/setup.c linux-mips/arch/i386/kernel/setup.c +--- linux-2.4.29/arch/i386/kernel/setup.c 2004-08-08 01:26:04.000000000 +0200 ++++ linux-mips/arch/i386/kernel/setup.c 2005-03-26 11:47:12.810549238 +0100 +@@ -354,7 +354,8 @@ + struct resource standard_io_resources[] = { + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, + { "pic1", 0x20, 0x3f, IORESOURCE_BUSY }, +- { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, ++ { "timer0", 0x40, 0x43, IORESOURCE_BUSY }, ++ { "timer1", 0x50, 0x53, IORESOURCE_BUSY }, + { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, + { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY }, +diff -Nur linux-2.4.29/arch/i386/lib/usercopy.c linux-mips/arch/i386/lib/usercopy.c +--- linux-2.4.29/arch/i386/lib/usercopy.c 2003-06-13 16:51:29.000000000 +0200 ++++ linux-mips/arch/i386/lib/usercopy.c 2005-03-26 11:47:12.859541197 +0100 +@@ -14,6 +14,7 @@ + unsigned long + __generic_copy_to_user(void *to, const void *from, unsigned long n) + { ++ BUG_ON((long) n < 0); + if (access_ok(VERIFY_WRITE, to, n)) + { + if(n<512) +@@ -27,6 +28,7 @@ + unsigned long + __generic_copy_from_user(void *to, const void *from, unsigned long n) + { ++ BUG_ON((long) n < 0); + if (access_ok(VERIFY_READ, from, n)) + { + if(n<512) +@@ -44,6 +46,7 @@ + unsigned long + __generic_copy_to_user(void *to, const void *from, unsigned long n) + { ++ BUG_ON((long) n < 0); + prefetch(from); + if (access_ok(VERIFY_WRITE, to, n)) + __copy_user(to,from,n); +@@ -53,6 +56,7 @@ + unsigned long + __generic_copy_from_user(void *to, const void *from, unsigned long n) + { ++ BUG_ON((long) n < 0); + prefetchw(to); + if (access_ok(VERIFY_READ, from, n)) + __copy_user_zeroing(to,from,n); +diff -Nur linux-2.4.29/arch/ia64/ia32/sys_ia32.c linux-mips/arch/ia64/ia32/sys_ia32.c +--- linux-2.4.29/arch/ia64/ia32/sys_ia32.c 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/ia64/ia32/sys_ia32.c 2005-03-26 11:47:12.934528890 +0100 +@@ -1649,7 +1649,8 @@ + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ + static void +-cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr) ++cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr, ++ __kernel_size_t orig_cmsg_len) + { + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; +@@ -1683,6 +1684,9 @@ + goto fail2; + + clen64 = kcmsg32->cmsg_len; ++ if ((clen64 < CMSG_ALIGN(sizeof(*ucmsg))) || ++ (clen64 > (orig_cmsg_len + wp - workbuf))) ++ break; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + +@@ -1812,6 +1816,7 @@ + struct iovec *iov=iovstack; + struct msghdr msg_sys; + unsigned long cmsg_ptr; ++ __kernel_size_t cmsg_len; + int err, iov_size, total_len, len; + struct scm_cookie scm; + +@@ -1856,6 +1861,7 @@ + total_len=err; + + cmsg_ptr = (unsigned long)msg_sys.msg_control; ++ cmsg_len = msg_sys.msg_controllen; + msg_sys.msg_flags = 0; + + if (sock->file->f_flags & O_NONBLOCK) +@@ -1882,7 +1888,8 @@ + * fix it up before we tack on more stuff. + */ + if ((unsigned long) msg_sys.msg_control != cmsg_ptr) +- cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr); ++ cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr, ++ cmsg_len); - obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o - obj-$(CONFIG_KGDB) += dbg_io.o + /* Wheee... */ + if (sock->passcred) diff -Nur linux-2.4.29/arch/mips/au1000/common/au1xxx_irqmap.c linux-mips/arch/mips/au1000/common/au1xxx_irqmap.c --- linux-2.4.29/arch/mips/au1000/common/au1xxx_irqmap.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-mips/arch/mips/au1000/common/au1xxx_irqmap.c 2005-01-31 12:59:30.000000000 +0100 @@ -184,7 +357,7 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/cputable.c linux-mips/arch/mips/a diff -Nur linux-2.4.29/arch/mips/au1000/common/dbdma.c linux-mips/arch/mips/au1000/common/dbdma.c --- linux-2.4.29/arch/mips/au1000/common/dbdma.c 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/common/dbdma.c 2005-02-12 04:05:28.000000000 +0100 ++++ linux-mips/arch/mips/au1000/common/dbdma.c 2005-03-26 11:47:17.214826394 +0100 @@ -41,6 +41,8 @@ #include <asm/au1xxx_dbdma.h> #include <asm/system.h> @@ -887,8 +1060,40 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/gpio.c linux-mips/arch/mips/au100 +EXPORT_SYMBOL(au1xxx_gpio_read); diff -Nur linux-2.4.29/arch/mips/au1000/common/irq.c linux-mips/arch/mips/au1000/common/irq.c --- linux-2.4.29/arch/mips/au1000/common/irq.c 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/common/irq.c 2005-01-31 12:59:30.000000000 +0100 -@@ -508,6 +508,7 @@ ++++ linux-mips/arch/mips/au1000/common/irq.c 2005-03-26 11:47:17.215826230 +0100 +@@ -303,8 +303,30 @@ + }; + + #ifdef CONFIG_PM +-void startup_match20_interrupt(void) ++void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)) + { ++ static struct irqaction action; ++ /* This is a big problem.... since we didn't use request_irq ++ when kernel/irq.c calls probe_irq_xxx this interrupt will ++ be probed for usage. This will end up disabling the device :( ++ ++ Give it a bogus "action" pointer -- this will keep it from ++ getting auto-probed! ++ ++ By setting the status to match that of request_irq() we ++ can avoid it. --cgray ++ */ ++ action.dev_id = handler; ++ action.flags = 0; ++ action.mask = 0; ++ action.name = "Au1xxx TOY"; ++ action.handler = handler; ++ action.next = NULL; ++ ++ irq_desc[AU1000_TOY_MATCH2_INT].action = &action; ++ irq_desc[AU1000_TOY_MATCH2_INT].status ++ &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); ++ + local_enable_irq(AU1000_TOY_MATCH2_INT); + } + #endif +@@ -508,6 +530,7 @@ if (!intc0_req0) return; @@ -896,7 +1101,7 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/irq.c linux-mips/arch/mips/au1000 /* * Because of the tight timing of SETUP token to reply * transactions, the USB devices-side packet complete -@@ -518,6 +519,7 @@ +@@ -518,6 +541,7 @@ do_IRQ(AU1000_USB_DEV_REQ_INT, regs); return; } @@ -904,6 +1109,40 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/irq.c linux-mips/arch/mips/au1000 irq = au_ffs(intc0_req0) - 1; intc0_req0 &= ~(1<<irq); +@@ -536,17 +560,7 @@ + + irq = au_ffs(intc0_req1) - 1; + intc0_req1 &= ~(1<<irq); +-#ifdef CONFIG_PM +- if (irq == AU1000_TOY_MATCH2_INT) { +- mask_and_ack_rise_edge_irq(irq); +- counter0_irq(irq, NULL, regs); +- local_enable_irq(irq); +- } +- else +-#endif +- { +- do_IRQ(irq, regs); +- } ++ do_IRQ(irq, regs); + } + + +diff -Nur linux-2.4.29/arch/mips/au1000/common/Makefile linux-mips/arch/mips/au1000/common/Makefile +--- linux-2.4.29/arch/mips/au1000/common/Makefile 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/au1000/common/Makefile 2005-01-31 12:59:30.000000000 +0100 +@@ -19,9 +19,9 @@ + export-objs = prom.o clocks.o power.o usbdev.o + + obj-y := prom.o int-handler.o irq.o puts.o time.o reset.o cputable.o \ +- au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o ++ au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o gpio.o + +-export-objs += dma.o dbdma.o ++export-objs += dma.o dbdma.o gpio.o + + obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o + obj-$(CONFIG_KGDB) += dbg_io.o diff -Nur linux-2.4.29/arch/mips/au1000/common/pci_fixup.c linux-mips/arch/mips/au1000/common/pci_fixup.c --- linux-2.4.29/arch/mips/au1000/common/pci_fixup.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-mips/arch/mips/au1000/common/pci_fixup.c 2004-12-03 09:00:32.000000000 +0100 @@ -925,7 +1164,7 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/pci_fixup.c linux-mips/arch/mips/ diff -Nur linux-2.4.29/arch/mips/au1000/common/pci_ops.c linux-mips/arch/mips/au1000/common/pci_ops.c --- linux-2.4.29/arch/mips/au1000/common/pci_ops.c 2004-02-18 14:36:30.000000000 +0100 -+++ linux-mips/arch/mips/au1000/common/pci_ops.c 2005-01-31 12:59:30.000000000 +0100 ++++ linux-mips/arch/mips/au1000/common/pci_ops.c 2005-03-26 11:47:17.258819174 +0100 @@ -162,6 +162,7 @@ static int config_access(unsigned char access_type, struct pci_dev *dev, unsigned char where, u32 * data) @@ -942,7 +1181,19 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/pci_ops.c linux-mips/arch/mips/au unsigned long entryLo0, entryLo1; if (device > 19) { -@@ -271,8 +271,11 @@ +@@ -205,9 +205,8 @@ + last_entryLo0 = last_entryLo1 = 0xffffffff; + } + +- /* Since the Au1xxx doesn't do the idsel timing exactly to spec, +- * many board vendors implement their own off-chip idsel, so call +- * it now. If it doesn't succeed, may as well bail out at this point. ++ /* Allow board vendors to implement their own off-chip idsel. ++ * If it doesn't succeed, may as well bail out at this point. + */ + if (board_pci_idsel) { + if (board_pci_idsel(device, 1) == 0) { +@@ -271,8 +270,11 @@ } local_irq_restore(flags); @@ -1168,6 +1419,89 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/power.c linux-mips/arch/mips/au10 {0} }; +diff -Nur linux-2.4.29/arch/mips/au1000/common/reset.c linux-mips/arch/mips/au1000/common/reset.c +--- linux-2.4.29/arch/mips/au1000/common/reset.c 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/au1000/common/reset.c 2005-03-26 11:47:17.264818189 +0100 +@@ -37,8 +37,6 @@ + #include <asm/system.h> + #include <asm/au1000.h> + +-extern int au_sleep(void); +- + void au1000_restart(char *command) + { + /* Set all integrated peripherals to disabled states */ +@@ -144,6 +142,26 @@ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; ++ case 0x04000000: /* Au1200 */ ++ au_writel(0x00, 0xb400300c); /* ddma */ ++ au_writel(0x00, 0xb1a00004); /* psc 0 */ ++ au_writel(0x00, 0xb1b00004); /* psc 1 */ ++ au_writel(0x00d02000, 0xb4020004); /* ehci, ohci, udc, otg */ ++ au_writel(0x00, 0xb5000004); /* lcd */ ++ au_writel(0x00, 0xb060000c); /* sd0 */ ++ au_writel(0x00, 0xb068000c); /* sd1 */ ++ au_writel(0x00, 0xb1100100); /* swcnt */ ++ au_writel(0x00, 0xb0300000); /* aes */ ++ au_writel(0x00, 0xb4004000); /* cim */ ++ au_writel(0x00, 0xb1100100); /* uart0_enable */ ++ au_writel(0x00, 0xb1200100); /* uart1_enable */ ++ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ ++ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ ++ au_writel(0x00, 0xb1900028); /* sys_clksrc */ ++ au_writel(0x10, 0xb1900060); /* sys_cpupll */ ++ au_writel(0x00, 0xb1900064); /* sys_auxpll */ ++ au_writel(0x00, 0xb1900100); /* sys_pininputen */ ++ break; + + default: + break; +@@ -163,32 +181,23 @@ + + void au1000_halt(void) + { +-#if defined(CONFIG_MIPS_PB1550) +- /* power off system */ +- printk("\n** Powering off Pb1550\n"); +- au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C); +- au_sync(); +- while(1); /* should not get here */ +-#endif +- printk(KERN_NOTICE "\n** You can safely turn off the power\n"); +-#ifdef CONFIG_MIPS_MIRAGE +- au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT); +-#endif +-#ifdef CONFIG_PM +- au_sleep(); +- +- /* should not get here */ +- printk(KERN_ERR "Unable to put cpu in sleep mode\n"); +- while(1); +-#else +- while (1) ++ /* Use WAIT in a low-power infinite spin loop */ ++ while (1) { + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +-#endif ++ } + } + + void au1000_power_off(void) + { ++ extern void board_power_off (void); ++ ++ printk(KERN_NOTICE "\n** You can safely turn off the power\n"); ++ ++ /* Give board a chance to power-off */ ++ board_power_off(); ++ ++ /* If board can't power-off, spin forever */ + au1000_halt(); + } diff -Nur linux-2.4.29/arch/mips/au1000/common/setup.c linux-mips/arch/mips/au1000/common/setup.c --- linux-2.4.29/arch/mips/au1000/common/setup.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-mips/arch/mips/au1000/common/setup.c 2005-01-31 12:59:30.000000000 +0100 @@ -1538,8 +1872,25 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/sleeper.S linux-mips/arch/mips/au + diff -Nur linux-2.4.29/arch/mips/au1000/common/time.c linux-mips/arch/mips/au1000/common/time.c --- linux-2.4.29/arch/mips/au1000/common/time.c 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/common/time.c 2005-01-31 12:59:30.000000000 +0100 -@@ -437,9 +437,6 @@ ++++ linux-mips/arch/mips/au1000/common/time.c 2005-03-26 11:47:17.265818025 +0100 +@@ -50,7 +50,6 @@ + #include <linux/mc146818rtc.h> + #include <linux/timex.h> + +-extern void startup_match20_interrupt(void); + extern void do_softirq(void); + extern volatile unsigned long wall_jiffies; + unsigned long missed_heart_beats = 0; +@@ -66,7 +65,7 @@ + + #ifdef CONFIG_PM + #define MATCH20_INC 328 +-extern void startup_match20_interrupt(void); ++extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)); + static unsigned long last_pc0, last_match20; + #endif + +@@ -437,9 +436,6 @@ au_writel(0, SYS_TOYWRITE); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); @@ -1549,24 +1900,18 @@ diff -Nur linux-2.4.29/arch/mips/au1000/common/time.c linux-mips/arch/mips/au100 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); /* setup match20 to interrupt once every 10ms */ -diff -Nur linux-2.4.29/arch/mips/au1000/db1x00/Makefile linux-mips/arch/mips/au1000/db1x00/Makefile ---- linux-2.4.29/arch/mips/au1000/db1x00/Makefile 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/db1x00/Makefile 2005-01-31 12:59:30.000000000 +0100 -@@ -17,4 +17,11 @@ - obj-y := init.o board_setup.o irqmap.o - obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o +@@ -447,7 +443,7 @@ + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); +- startup_match20_interrupt(); ++ startup_match20_interrupt(counter0_irq); + + do_gettimeoffset = do_fast_pm_gettimeoffset; -+ifdef CONFIG_MIPS_DB1100 -+ifdef CONFIG_MMC -+obj-y += mmc_support.o -+export-objs += mmc_support.o -+endif -+endif -+ - include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/arch/mips/au1000/db1x00/board_setup.c linux-mips/arch/mips/au1000/db1x00/board_setup.c --- linux-2.4.29/arch/mips/au1000/db1x00/board_setup.c 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/db1x00/board_setup.c 2005-01-31 12:59:30.000000000 +0100 ++++ linux-mips/arch/mips/au1000/db1x00/board_setup.c 2005-03-26 11:47:17.271817041 +0100 @@ -46,10 +46,22 @@ #include <asm/au1000.h> #include <asm/db1x00.h> @@ -1593,7 +1938,21 @@ diff -Nur linux-2.4.29/arch/mips/au1000/db1x00/board_setup.c linux-mips/arch/mip void board_reset (void) { -@@ -108,8 +120,42 @@ +@@ -57,6 +69,13 @@ + au_writel(0x00000000, 0xAE00001C); + } + ++void board_power_off (void) ++{ ++#ifdef CONFIG_MIPS_MIRAGE ++ au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT); ++#endif ++} ++ + void __init board_setup(void) + { + u32 pin_func; +@@ -108,8 +127,42 @@ au_writel(0x02000200, GPIO2_OUTPUT); #endif @@ -1647,6 +2006,21 @@ diff -Nur linux-2.4.29/arch/mips/au1000/db1x00/irqmap.c linux-mips/arch/mips/au1 #else { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 Fully_Interted# { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 STSCHG# +diff -Nur linux-2.4.29/arch/mips/au1000/db1x00/Makefile linux-mips/arch/mips/au1000/db1x00/Makefile +--- linux-2.4.29/arch/mips/au1000/db1x00/Makefile 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/au1000/db1x00/Makefile 2005-01-31 12:59:30.000000000 +0100 +@@ -17,4 +17,11 @@ + obj-y := init.o board_setup.o irqmap.o + obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o + ++ifdef CONFIG_MIPS_DB1100 ++ifdef CONFIG_MMC ++obj-y += mmc_support.o ++export-objs += mmc_support.o ++endif ++endif ++ + include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/arch/mips/au1000/db1x00/mmc_support.c linux-mips/arch/mips/au1000/db1x00/mmc_support.c --- linux-2.4.29/arch/mips/au1000/db1x00/mmc_support.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/arch/mips/au1000/db1x00/mmc_support.c 2005-01-30 09:07:01.000000000 +0100 @@ -1777,35 +2151,6 @@ diff -Nur linux-2.4.29/arch/mips/au1000/db1x00/mmc_support.c linux-mips/arch/mip +EXPORT_SYMBOL(mmc_power_on); +EXPORT_SYMBOL(mmc_power_off); + -diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/Makefile linux-mips/arch/mips/au1000/ficmmp/Makefile ---- linux-2.4.29/arch/mips/au1000/ficmmp/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/arch/mips/au1000/ficmmp/Makefile 2005-01-30 09:01:27.000000000 +0100 -@@ -0,0 +1,25 @@ -+# -+# Copyright 2000 MontaVista Software Inc. -+# Author: MontaVista Software, Inc. -+# ppopov@mvista.com or source@mvista.com -+# -+# Makefile for the Alchemy Semiconductor FIC board. -+# -+# Note! Dependencies are done automagically by 'make dep', which also -+# removes any old dependencies. DON'T put your own dependencies here -+# unless it's something special (ie not a .c file). -+# -+ -+USE_STANDARD_AS_RULE := true -+ -+O_TARGET := ficmmp.o -+ -+obj-y := init.o board_setup.o irqmap.o au1200_ibutton.o au1xxx_dock.o -+ -+ifdef CONFIG_MMC -+obj-y += mmc_support.o -+export-objs +=mmc_support.o -+endif -+ -+ -+include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/au1200_ibutton.c linux-mips/arch/mips/au1000/ficmmp/au1200_ibutton.c --- linux-2.4.29/arch/mips/au1000/ficmmp/au1200_ibutton.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/arch/mips/au1000/ficmmp/au1200_ibutton.c 2005-02-03 07:35:29.000000000 +0100 @@ -2347,8 +2692,8 @@ diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/au1xxx_dock.c linux-mips/arch/mip +module_exit(au1xxx_dock_exit); diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/board_setup.c linux-mips/arch/mips/au1000/ficmmp/board_setup.c --- linux-2.4.29/arch/mips/au1000/ficmmp/board_setup.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/arch/mips/au1000/ficmmp/board_setup.c 2005-01-30 09:01:27.000000000 +0100 -@@ -0,0 +1,191 @@ ++++ linux-mips/arch/mips/au1000/ficmmp/board_setup.c 2005-03-19 08:17:51.000000000 +0100 +@@ -0,0 +1,226 @@ +/* + * + * BRIEF MODULE DESCRIPTION @@ -2425,6 +2770,10 @@ diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/board_setup.c linux-mips/arch/mip + au_writel(0, 0xAD80001C); +} + ++void board_power_off (void) ++{ ++} ++ +void __init board_setup(void) +{ + char *argptr = NULL; @@ -2485,7 +2834,7 @@ diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/board_setup.c linux-mips/arch/mip + +#ifdef CONFIG_FB_AU1200 + argptr = prom_getcmdline(); -+ strcat(argptr, " video=au1200fb:panel:s11"); ++ strcat(argptr, " video=au1200fb:"); +#endif + +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) @@ -2540,6 +2889,37 @@ diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/board_setup.c linux-mips/arch/mip + printk("B190002C: %X\n", *((volatile u32*)0xB190002C)); +} + ++int ++board_au1200fb_panel (void) ++{ ++ au1xxx_gpio_tristate(6); ++ ++ if (au1xxx_gpio_read(12) == 0) ++ return 9; /* FS453_640x480 (Composite/S-Video) */ ++ else ++ return 7; /* Sharp 320x240 TFT */ ++} ++ ++int ++board_au1200fb_panel_init (void) ++{ ++ /*Enable data buffers*/ ++ ficmmp_config_clear(FICMMP_CONFIG_LCMDATAOUT); ++ /*Take LCD out of reset*/ ++ ficmmp_config_set(FICMMP_CONFIG_LCMPWREN | FICMMP_CONFIG_LCMEN); ++ return 0; ++} ++ ++int ++board_au1200fb_panel_shutdown (void) ++{ ++ /*Disable data buffers*/ ++ ficmmp_config_set(FICMMP_CONFIG_LCMDATAOUT); ++ /*Put LCD in reset, remove power*/ ++ ficmmp_config_clear(FICMMP_CONFIG_LCMEN | FICMMP_CONFIG_LCMPWREN); ++ return 0; ++} ++ diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/init.c linux-mips/arch/mips/au1000/ficmmp/init.c --- linux-2.4.29/arch/mips/au1000/ficmmp/init.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/arch/mips/au1000/ficmmp/init.c 2005-01-30 09:01:27.000000000 +0100 @@ -2685,26 +3065,49 @@ diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/irqmap.c linux-mips/arch/mips/au1 + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); + -diff -Nur linux-2.4.29/arch/mips/au1000/hydrogen3/Makefile linux-mips/arch/mips/au1000/hydrogen3/Makefile ---- linux-2.4.29/arch/mips/au1000/hydrogen3/Makefile 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/hydrogen3/Makefile 2005-02-12 04:05:28.000000000 +0100 -@@ -14,6 +14,11 @@ - - O_TARGET := hydrogen3.o - --obj-y := init.o board_setup.o irqmap.o -+obj-y := init.o board_setup.o irqmap.o buttons.o +diff -Nur linux-2.4.29/arch/mips/au1000/ficmmp/Makefile linux-mips/arch/mips/au1000/ficmmp/Makefile +--- linux-2.4.29/arch/mips/au1000/ficmmp/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-mips/arch/mips/au1000/ficmmp/Makefile 2005-01-30 09:01:27.000000000 +0100 +@@ -0,0 +1,25 @@ ++# ++# Copyright 2000 MontaVista Software Inc. ++# Author: MontaVista Software, Inc. ++# ppopov@mvista.com or source@mvista.com ++# ++# Makefile for the Alchemy Semiconductor FIC board. ++# ++# Note! Dependencies are done automagically by 'make dep', which also ++# removes any old dependencies. DON'T put your own dependencies here ++# unless it's something special (ie not a .c file). ++# ++ ++USE_STANDARD_AS_RULE := true ++ ++O_TARGET := ficmmp.o ++ ++obj-y := init.o board_setup.o irqmap.o au1200_ibutton.o au1xxx_dock.o + +ifdef CONFIG_MMC +obj-y += mmc_support.o +export-objs +=mmc_support.o +endif - - include $(TOPDIR)/Rules.make ++ ++ ++include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/arch/mips/au1000/hydrogen3/board_setup.c linux-mips/arch/mips/au1000/hydrogen3/board_setup.c --- linux-2.4.29/arch/mips/au1000/hydrogen3/board_setup.c 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/hydrogen3/board_setup.c 2005-01-31 12:59:30.000000000 +0100 -@@ -57,6 +57,9 @@ ++++ linux-mips/arch/mips/au1000/hydrogen3/board_setup.c 2005-03-26 11:47:17.377799647 +0100 +@@ -51,12 +51,19 @@ + { + } + ++void board_power_off (void) ++{ ++} ++ + void __init board_setup(void) + { + u32 pin_func; rtc_ops = &no_rtc_ops; @@ -3026,6 +3429,22 @@ diff -Nur linux-2.4.29/arch/mips/au1000/hydrogen3/buttons.c linux-mips/arch/mips + +module_init(hydrogen3_buttons_init); +module_exit(hydrogen3_buttons_exit); +diff -Nur linux-2.4.29/arch/mips/au1000/hydrogen3/Makefile linux-mips/arch/mips/au1000/hydrogen3/Makefile +--- linux-2.4.29/arch/mips/au1000/hydrogen3/Makefile 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/au1000/hydrogen3/Makefile 2005-03-26 11:47:17.372800467 +0100 +@@ -14,6 +14,11 @@ + + O_TARGET := hydrogen3.o + +-obj-y := init.o board_setup.o irqmap.o ++obj-y := init.o board_setup.o irqmap.o buttons.o ++ ++ifdef CONFIG_MMC ++obj-y += mmc_support.o ++export-objs +=mmc_support.o ++endif + + include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/arch/mips/au1000/hydrogen3/mmc_support.c linux-mips/arch/mips/au1000/hydrogen3/mmc_support.c --- linux-2.4.29/arch/mips/au1000/hydrogen3/mmc_support.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/arch/mips/au1000/hydrogen3/mmc_support.c 2005-02-02 05:27:06.000000000 +0100 @@ -3153,6 +3572,34 @@ diff -Nur linux-2.4.29/arch/mips/au1000/mtx-1/irqmap.c linux-mips/arch/mips/au10 }; const long min_idsel = 0, max_idsel = 3, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; +diff -Nur linux-2.4.29/arch/mips/au1000/pb1000/board_setup.c linux-mips/arch/mips/au1000/pb1000/board_setup.c +--- linux-2.4.29/arch/mips/au1000/pb1000/board_setup.c 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/au1000/pb1000/board_setup.c 2005-03-26 11:47:17.413793739 +0100 +@@ -58,6 +58,10 @@ + { + } + ++void board_power_off (void) ++{ ++} ++ + void __init board_setup(void) + { + u32 pin_func, static_cfg0; +diff -Nur linux-2.4.29/arch/mips/au1000/pb1100/board_setup.c linux-mips/arch/mips/au1000/pb1100/board_setup.c +--- linux-2.4.29/arch/mips/au1000/pb1100/board_setup.c 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/au1000/pb1100/board_setup.c 2005-03-26 11:47:17.418792919 +0100 +@@ -62,6 +62,10 @@ + au_writel(0x00000000, 0xAE00001C); + } + ++void board_power_off (void) ++{ ++} ++ + void __init board_setup(void) + { + u32 pin_func; diff -Nur linux-2.4.29/arch/mips/au1000/pb1100/Makefile linux-mips/arch/mips/au1000/pb1100/Makefile --- linux-2.4.29/arch/mips/au1000/pb1100/Makefile 2003-08-25 13:44:39.000000000 +0200 +++ linux-mips/arch/mips/au1000/pb1100/Makefile 2005-01-31 12:59:30.000000000 +0100 @@ -3297,39 +3744,10 @@ diff -Nur linux-2.4.29/arch/mips/au1000/pb1100/mmc_support.c linux-mips/arch/mip +EXPORT_SYMBOL(mmc_power_on); +EXPORT_SYMBOL(mmc_power_off); + -diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/Makefile linux-mips/arch/mips/au1000/pb1200/Makefile ---- linux-2.4.29/arch/mips/au1000/pb1200/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/arch/mips/au1000/pb1200/Makefile 2005-01-30 09:01:27.000000000 +0100 -@@ -0,0 +1,25 @@ -+# -+# Copyright 2000 MontaVista Software Inc. -+# Author: MontaVista Software, Inc. -+# ppopov@mvista.com or source@mvista.com -+# -+# Makefile for the Alchemy Semiconductor PB1000 board. -+# -+# Note! Dependencies are done automagically by 'make dep', which also -+# removes any old dependencies. DON'T put your own dependencies here -+# unless it's something special (ie not a .c file). -+# -+ -+USE_STANDARD_AS_RULE := true -+ -+O_TARGET := pb1200.o -+ -+obj-y := init.o board_setup.o irqmap.o -+ -+ifdef CONFIG_MMC -+obj-y += mmc_support.o -+export-objs +=mmc_support.o -+endif -+ -+ -+include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/board_setup.c linux-mips/arch/mips/au1000/pb1200/board_setup.c --- linux-2.4.29/arch/mips/au1000/pb1200/board_setup.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/arch/mips/au1000/pb1200/board_setup.c 2005-01-30 09:01:28.000000000 +0100 -@@ -0,0 +1,190 @@ ++++ linux-mips/arch/mips/au1000/pb1200/board_setup.c 2005-03-19 08:17:51.000000000 +0100 +@@ -0,0 +1,221 @@ +/* + * + * BRIEF MODULE DESCRIPTION @@ -3413,6 +3831,11 @@ diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/board_setup.c linux-mips/arch/mip + bcsr->resets = 0; +} + ++void board_power_off (void) ++{ ++ bcsr->resets = 0xC000; ++} ++ +void __init board_setup(void) +{ + char *argptr = NULL; @@ -3471,12 +3894,7 @@ diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/board_setup.c linux-mips/arch/mip + +#ifdef CONFIG_FB_AU1200 + argptr = prom_getcmdline(); -+#ifdef CONFIG_MIPS_PB1200 -+ strcat(argptr, " video=au1200fb:panel:s11"); -+#endif -+#ifdef CONFIG_MIPS_DB1200 -+ strcat(argptr, " video=au1200fb:panel:s7"); -+#endif ++ strcat(argptr, " video=au1200fb:"); +#endif + +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) @@ -3520,6 +3938,37 @@ diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/board_setup.c linux-mips/arch/mip + board_init_irq = _board_init_irq; + } +} ++ ++int ++board_au1200fb_panel (void) ++{ ++ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; ++ int p; ++ ++ p = bcsr->switches; ++ p >>= 8; ++ p &= 0x0F; ++ return p; ++} ++ ++int ++board_au1200fb_panel_init (void) ++{ ++ /* Apply power */ ++ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; ++ bcsr->board |= (BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL); ++ return 0; ++} ++ ++int ++board_au1200fb_panel_shutdown (void) ++{ ++ /* Remove power */ ++ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; ++ bcsr->board &= ~(BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL); ++ return 0; ++} ++ diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/init.c linux-mips/arch/mips/au1000/pb1200/init.c --- linux-2.4.29/arch/mips/au1000/pb1200/init.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/arch/mips/au1000/pb1200/init.c 2005-01-30 09:01:28.000000000 +0100 @@ -3780,6 +4229,35 @@ diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/irqmap.c linux-mips/arch/mips/au1 + request of any source attached to the cascade */ +} + +diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/Makefile linux-mips/arch/mips/au1000/pb1200/Makefile +--- linux-2.4.29/arch/mips/au1000/pb1200/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-mips/arch/mips/au1000/pb1200/Makefile 2005-01-30 09:01:27.000000000 +0100 +@@ -0,0 +1,25 @@ ++# ++# Copyright 2000 MontaVista Software Inc. ++# Author: MontaVista Software, Inc. ++# ppopov@mvista.com or source@mvista.com ++# ++# Makefile for the Alchemy Semiconductor PB1000 board. ++# ++# Note! Dependencies are done automagically by 'make dep', which also ++# removes any old dependencies. DON'T put your own dependencies here ++# unless it's something special (ie not a .c file). ++# ++ ++USE_STANDARD_AS_RULE := true ++ ++O_TARGET := pb1200.o ++ ++obj-y := init.o board_setup.o irqmap.o ++ ++ifdef CONFIG_MMC ++obj-y += mmc_support.o ++export-objs +=mmc_support.o ++endif ++ ++ ++include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/mmc_support.c linux-mips/arch/mips/au1000/pb1200/mmc_support.c --- linux-2.4.29/arch/mips/au1000/pb1200/mmc_support.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/arch/mips/au1000/pb1200/mmc_support.c 2005-01-30 09:01:28.000000000 +0100 @@ -3925,10 +4403,24 @@ diff -Nur linux-2.4.29/arch/mips/au1000/pb1200/mmc_support.c linux-mips/arch/mip +EXPORT_SYMBOL(mmc_power_on); +EXPORT_SYMBOL(mmc_power_off); + +diff -Nur linux-2.4.29/arch/mips/au1000/pb1500/board_setup.c linux-mips/arch/mips/au1000/pb1500/board_setup.c +--- linux-2.4.29/arch/mips/au1000/pb1500/board_setup.c 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/au1000/pb1500/board_setup.c 2005-03-26 11:47:17.496780119 +0100 +@@ -62,6 +62,10 @@ + au_writel(0x00000000, 0xAE00001C); + } + ++void board_power_off (void) ++{ ++} ++ + void __init board_setup(void) + { + u32 pin_func; diff -Nur linux-2.4.29/arch/mips/au1000/pb1550/board_setup.c linux-mips/arch/mips/au1000/pb1550/board_setup.c --- linux-2.4.29/arch/mips/au1000/pb1550/board_setup.c 2005-01-19 15:09:26.000000000 +0100 -+++ linux-mips/arch/mips/au1000/pb1550/board_setup.c 2005-01-31 12:59:30.000000000 +0100 -@@ -48,6 +48,16 @@ ++++ linux-mips/arch/mips/au1000/pb1550/board_setup.c 2005-03-26 11:47:17.496780119 +0100 +@@ -48,12 +48,31 @@ extern struct rtc_ops no_rtc_ops; @@ -3945,7 +4437,22 @@ diff -Nur linux-2.4.29/arch/mips/au1000/pb1550/board_setup.c linux-mips/arch/mip void board_reset (void) { /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ -@@ -78,5 +88,36 @@ + au_writew(au_readw(0xAF00001C) & ~(1<<15), 0xAF00001C); + } + ++void board_power_off (void) ++{ ++ /* power off system */ ++ printk("\n** Powering off Pb1550\n"); ++ au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C); ++ au_sync(); ++ while(1); /* should not get here */ ++} ++ + void __init board_setup(void) + { + u32 pin_func; +@@ -78,5 +97,36 @@ au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */ au_sync(); @@ -4120,7 +4627,17 @@ diff -Nur linux-2.4.29/arch/mips/config-shared.in linux-mips/arch/mips/config-sh "$CONFIG_NINO" = "y" -o \ diff -Nur linux-2.4.29/arch/mips/defconfig linux-mips/arch/mips/defconfig --- linux-2.4.29/arch/mips/defconfig 2005-01-19 15:09:27.000000000 +0100 -+++ linux-mips/arch/mips/defconfig 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig 2005-03-26 11:47:13.509434535 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -235,11 +235,6 @@ # # CONFIG_IPX is not set @@ -4133,7 +4650,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -319,6 +314,7 @@ +@@ -319,9 +314,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -4141,9 +4658,31 @@ diff -Nur linux-2.4.29/arch/mips/defconfig linux-mips/arch/mips/defconfig # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -465,7 +462,6 @@ + # CONFIG_SERIAL is not set + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-atlas linux-mips/arch/mips/defconfig-atlas --- linux-2.4.29/arch/mips/defconfig-atlas 2005-01-19 15:09:27.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-atlas 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-atlas 2005-03-26 11:47:13.579423048 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -235,11 +235,6 @@ # # CONFIG_IPX is not set @@ -4156,7 +4695,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-atlas linux-mips/arch/mips/defconfig- # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -317,6 +312,7 @@ +@@ -317,9 +312,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -4164,10 +4703,50 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-atlas linux-mips/arch/mips/defconfig- # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -528,7 +525,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-bosporus linux-mips/arch/mips/defconfig-bosporus --- linux-2.4.29/arch/mips/defconfig-bosporus 2005-01-19 15:09:27.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-bosporus 2005-01-31 12:59:28.000000000 +0100 -@@ -373,11 +373,6 @@ ++++ linux-mips/arch/mips/defconfig-bosporus 2005-03-26 11:47:13.674407459 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -208,9 +208,7 @@ + CONFIG_MTD_BOSPORUS=y + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -229,7 +227,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -373,11 +370,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -4179,7 +4758,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-bosporus linux-mips/arch/mips/defconf # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -457,6 +452,7 @@ +@@ -457,9 +449,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -4187,18 +4766,31 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-bosporus linux-mips/arch/mips/defconf # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set -@@ -899,7 +895,7 @@ - # CONFIG_USB_UHCI is not set - # CONFIG_USB_UHCI_ALT is not set - CONFIG_USB_OHCI=y -- -+CONFIG_USB_NON_PCI_OHCI=y - # - # USB Device Class drivers - # ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -681,7 +675,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-capcella linux-mips/arch/mips/defconfig-capcella --- linux-2.4.29/arch/mips/defconfig-capcella 2005-01-19 15:09:27.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-capcella 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-capcella 2005-03-26 11:47:13.739396793 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -228,11 +228,6 @@ # # CONFIG_IPX is not set @@ -4211,9 +4803,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-capcella linux-mips/arch/mips/defconf # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -472,7 +467,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-cobalt linux-mips/arch/mips/defconfig-cobalt --- linux-2.4.29/arch/mips/defconfig-cobalt 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-cobalt 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-cobalt 2005-03-26 11:47:13.804386126 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -222,11 +222,6 @@ # # CONFIG_IPX is not set @@ -4226,9 +4836,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-cobalt linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -505,7 +500,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=16 + diff -Nur linux-2.4.29/arch/mips/defconfig-csb250 linux-mips/arch/mips/defconfig-csb250 --- linux-2.4.29/arch/mips/defconfig-csb250 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-csb250 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-csb250 2005-03-26 11:47:13.887372506 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + CONFIG_COGENT_CSB250=y @@ -268,11 +268,6 @@ # # CONFIG_IPX is not set @@ -4241,31 +4869,48 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-csb250 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -556,7 +551,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-db1000 linux-mips/arch/mips/defconfig-db1000 --- linux-2.4.29/arch/mips/defconfig-db1000 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-db1000 2005-02-12 04:05:27.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - CONFIG_MIPS_DB1000=y - # CONFIG_MIPS_DB1100 is not set - # CONFIG_MIPS_DB1500 is not set - # CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-db1000 2005-03-26 11:47:13.987356097 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set # CONFIG_MIPS_PB1100 is not set # CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -342,11 +345,6 @@ +@@ -214,11 +214,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-CONFIG_MTD_DB1X00=y +-CONFIG_MTD_DB1X00_BOOT=y +-CONFIG_MTD_DB1X00_USER=y + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -237,7 +233,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -342,11 +337,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -4277,31 +4922,48 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1000 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -636,7 +626,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-db1100 linux-mips/arch/mips/defconfig-db1100 --- linux-2.4.29/arch/mips/defconfig-db1100 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-db1100 2005-02-12 04:05:27.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - CONFIG_MIPS_DB1100=y - # CONFIG_MIPS_DB1500 is not set - # CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-db1100 2005-03-26 11:47:14.088339523 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set # CONFIG_MIPS_PB1100 is not set # CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -342,11 +345,6 @@ +@@ -214,11 +214,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-CONFIG_MTD_DB1X00=y +-# CONFIG_MTD_DB1X00_BOOT is not set +-CONFIG_MTD_DB1X00_USER=y + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -237,7 +233,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -342,11 +337,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -4313,10 +4975,34 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1100 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -636,7 +626,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + +@@ -884,6 +873,7 @@ + # CONFIG_FB_PM2 is not set + # CONFIG_FB_PM3 is not set + # CONFIG_FB_CYBER2000 is not set ++CONFIG_FB_AU1100=y + # CONFIG_FB_MATROX is not set + # CONFIG_FB_ATY is not set + # CONFIG_FB_RADEON is not set +@@ -895,7 +885,6 @@ + # CONFIG_FB_VOODOO1 is not set + # CONFIG_FB_TRIDENT is not set + # CONFIG_FB_E1356 is not set +-CONFIG_FB_AU1100=y + # CONFIG_FB_IT8181 is not set + # CONFIG_FB_VIRTUAL is not set + CONFIG_FBCON_ADVANCED=y diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig-db1200 --- linux-2.4.29/arch/mips/defconfig-db1200 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-db1200 2005-01-30 09:01:26.000000000 +0100 -@@ -0,0 +1,1051 @@ ++++ linux-mips/arch/mips/defconfig-db1200 2005-03-26 11:47:14.182324098 +0100 +@@ -0,0 +1,1032 @@ +# +# Automatically generated make config: don't edit +# @@ -4341,18 +5027,15 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set -+CONFIG_MIPS_DB1200=y +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set @@ -4399,10 +5082,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# CONFIG_HIGHMEM is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -+CONFIG_SOC_AU1X00=y -+CONFIG_SOC_AU1200=y -+CONFIG_NONCOHERENT_IO=y -+CONFIG_PC_KEYB=y +# CONFIG_MIPS_AU1000 is not set + +# @@ -4461,7 +5140,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# CONFIG_TCIC is not set +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set -+CONFIG_PCMCIA_AU1X00=m + +# +# PCI Hotplug Support @@ -4488,7 +5166,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# CONFIG_OOM_KILLER is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="mem=96M" -+# CONFIG_PM is not set + +# +# Memory Technology Devices (MTD) @@ -4710,6 +5387,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set @@ -4798,7 +5476,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y -+# CONFIG_MIPS_AU1X00_ENET is not set +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set @@ -4911,12 +5588,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# CONFIG_SERIAL_TX3912_CONSOLE is not set +# CONFIG_SERIAL_TXX9 is not set +# CONFIG_SERIAL_TXX9_CONSOLE is not set -+CONFIG_AU1X00_UART=y -+CONFIG_AU1X00_SERIAL_CONSOLE=y -+# CONFIG_AU1X00_USB_TTY is not set -+# CONFIG_AU1X00_USB_RAW is not set +# CONFIG_TXX927_SERIAL is not set -+# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + @@ -5001,8 +5673,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# +# CONFIG_PCMCIA_SERIAL_CS is not set +# CONFIG_SYNCLINK_CS is not set -+# CONFIG_AU1X00_GPIO is not set -+# CONFIG_TS_AU1X00_ADS7846 is not set + +# +# File systems @@ -5224,9 +5894,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set -+# CONFIG_SOUND_AU1X00 is not set -+CONFIG_SOUND_AU1550_PSC=y -+# CONFIG_SOUND_AU1550_I2S is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set @@ -5370,29 +6037,18 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1200 linux-mips/arch/mips/defconfig +# CONFIG_FW_LOADER is not set diff -Nur linux-2.4.29/arch/mips/defconfig-db1500 linux-mips/arch/mips/defconfig-db1500 --- linux-2.4.29/arch/mips/defconfig-db1500 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-db1500 2005-02-12 04:05:27.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - # CONFIG_MIPS_DB1100 is not set - CONFIG_MIPS_DB1500=y - # CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-db1500 2005-03-26 11:47:14.271309493 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set # CONFIG_MIPS_PB1100 is not set # CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -267,11 +270,6 @@ +@@ -267,11 +267,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -5404,31 +6060,48 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1500 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -555,7 +550,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-db1550 linux-mips/arch/mips/defconfig-db1550 --- linux-2.4.29/arch/mips/defconfig-db1550 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-db1550 2005-02-12 04:05:27.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - # CONFIG_MIPS_DB1100 is not set - # CONFIG_MIPS_DB1500 is not set - CONFIG_MIPS_DB1550=y -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-db1550 2005-03-26 11:47:14.372292920 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set # CONFIG_MIPS_PB1100 is not set # CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -343,11 +346,6 @@ +@@ -213,11 +213,9 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + CONFIG_MTD_PB1550=y + CONFIG_MTD_PB1550_BOOT=y + CONFIG_MTD_PB1550_USER=y +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -236,7 +234,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -343,11 +340,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -5440,9 +6113,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-db1550 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -633,7 +625,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-ddb5476 linux-mips/arch/mips/defconfig-ddb5476 --- linux-2.4.29/arch/mips/defconfig-ddb5476 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ddb5476 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-ddb5476 2005-03-26 11:47:14.442281433 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -226,11 +226,6 @@ # # CONFIG_IPX is not set @@ -5455,9 +6146,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ddb5476 linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -517,7 +512,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-ddb5477 linux-mips/arch/mips/defconfig-ddb5477 --- linux-2.4.29/arch/mips/defconfig-ddb5477 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ddb5477 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-ddb5477 2005-03-26 11:47:14.507270767 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -226,11 +226,6 @@ # # CONFIG_IPX is not set @@ -5470,9 +6179,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ddb5477 linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -434,7 +429,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-decstation linux-mips/arch/mips/defconfig-decstation --- linux-2.4.29/arch/mips/defconfig-decstation 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-decstation 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-decstation 2005-03-26 11:47:14.573259936 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -223,11 +223,6 @@ # # CONFIG_IPX is not set @@ -5485,7 +6212,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-decstation linux-mips/arch/mips/defco # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -306,6 +301,7 @@ +@@ -306,9 +301,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -5493,9 +6220,31 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-decstation linux-mips/arch/mips/defco # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -477,7 +474,6 @@ + CONFIG_SERIAL_DEC_CONSOLE=y + CONFIG_DZ=y + CONFIG_ZS=y +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-e55 linux-mips/arch/mips/defconfig-e55 --- linux-2.4.29/arch/mips/defconfig-e55 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-e55 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-e55 2005-03-26 11:47:14.632250255 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -222,11 +222,6 @@ # # CONFIG_IPX is not set @@ -5508,10 +6257,57 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-e55 linux-mips/arch/mips/defconfig-e5 # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -426,7 +421,6 @@ + # CONFIG_SERIAL_MULTIPORT is not set + # CONFIG_HUB6 is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-eagle linux-mips/arch/mips/defconfig-eagle --- linux-2.4.29/arch/mips/defconfig-eagle 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-eagle 2005-01-09 20:33:59.000000000 +0100 -@@ -327,11 +327,6 @@ ++++ linux-mips/arch/mips/defconfig-eagle 2005-03-26 11:47:14.721235650 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -208,8 +208,8 @@ + # Mapping drivers for chip access + # + CONFIG_MTD_PHYSMAP=y +-CONFIG_MTD_PHYSMAP_START=1c000000 +-CONFIG_MTD_PHYSMAP_LEN=2000000 ++CONFIG_MTD_PHYSMAP_START=0x1c000000 ++CONFIG_MTD_PHYSMAP_LEN=0x2000000 + CONFIG_MTD_PHYSMAP_BUSWIDTH=4 + # CONFIG_MTD_PB1000 is not set + # CONFIG_MTD_PB1500 is not set +@@ -217,9 +217,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -238,7 +236,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -327,11 +324,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -5523,9 +6319,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-eagle linux-mips/arch/mips/defconfig- # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -587,7 +579,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-ev64120 linux-mips/arch/mips/defconfig-ev64120 --- linux-2.4.29/arch/mips/defconfig-ev64120 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ev64120 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-ev64120 2005-03-26 11:47:14.780225968 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -230,11 +230,6 @@ # # CONFIG_IPX is not set @@ -5538,9 +6352,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ev64120 linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -443,7 +438,6 @@ + # CONFIG_SERIAL_CONSOLE is not set + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-ev96100 linux-mips/arch/mips/defconfig-ev96100 --- linux-2.4.29/arch/mips/defconfig-ev96100 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ev96100 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-ev96100 2005-03-26 11:47:14.833217271 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -232,11 +232,6 @@ # # CONFIG_IPX is not set @@ -5553,10 +6385,18 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ev96100 linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -441,7 +436,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig-ficmmp --- linux-2.4.29/arch/mips/defconfig-ficmmp 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ficmmp 2005-02-12 04:05:27.000000000 +0100 -@@ -0,0 +1,880 @@ ++++ linux-mips/arch/mips/defconfig-ficmmp 2005-03-26 11:47:14.922202667 +0100 +@@ -0,0 +1,862 @@ +# +# Automatically generated make config: don't edit +# @@ -5581,18 +6421,15 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_MIPS_BOSPORUS is not set -+CONFIG_MIPS_FICMMP=y +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set @@ -5639,10 +6476,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# CONFIG_HIGHMEM is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -+CONFIG_SOC_AU1X00=y -+CONFIG_SOC_AU1200=y -+CONFIG_NONCOHERENT_IO=y -+CONFIG_PC_KEYB=y +# CONFIG_MIPS_AU1000 is not set + +# @@ -5708,7 +6541,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# CONFIG_OOM_KILLER is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ide3=dma mem=96M root=/dev/hda2 rootflags=data=journal" -+# CONFIG_PM is not set + +# +# Memory Technology Devices (MTD) @@ -5925,6 +6757,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set @@ -5985,7 +6818,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y -+# CONFIG_MIPS_AU1X00_ENET is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set @@ -6091,12 +6923,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# CONFIG_SERIAL_TX3912_CONSOLE is not set +# CONFIG_SERIAL_TXX9 is not set +# CONFIG_SERIAL_TXX9_CONSOLE is not set -+CONFIG_AU1X00_UART=y -+CONFIG_AU1X00_SERIAL_CONSOLE=y -+# CONFIG_AU1X00_USB_TTY is not set -+# CONFIG_AU1X00_USB_RAW is not set +# CONFIG_TXX927_SERIAL is not set -+# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + @@ -6180,8 +7007,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# Direct Rendering Manager (XFree86 DRI support) +# +# CONFIG_DRM is not set -+# CONFIG_AU1X00_GPIO is not set -+# CONFIG_TS_AU1X00_ADS7846 is not set + +# +# File systems @@ -6386,9 +7211,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set -+# CONFIG_SOUND_AU1X00 is not set -+# CONFIG_SOUND_AU1550_PSC is not set -+# CONFIG_SOUND_AU1550_I2S is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set @@ -6439,8 +7261,47 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ficmmp linux-mips/arch/mips/defconfig +CONFIG_ZLIB_DEFLATE=m diff -Nur linux-2.4.29/arch/mips/defconfig-hp-lj linux-mips/arch/mips/defconfig-hp-lj --- linux-2.4.29/arch/mips/defconfig-hp-lj 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-hp-lj 2005-01-09 20:33:59.000000000 +0100 -@@ -304,11 +304,6 @@ ++++ linux-mips/arch/mips/defconfig-hp-lj 2005-03-26 11:47:14.993191016 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -184,8 +184,8 @@ + # Mapping drivers for chip access + # + CONFIG_MTD_PHYSMAP=y +-CONFIG_MTD_PHYSMAP_START=10040000 +-CONFIG_MTD_PHYSMAP_LEN=00fc0000 ++CONFIG_MTD_PHYSMAP_START=0x10040000 ++CONFIG_MTD_PHYSMAP_LEN=0x00fc0000 + CONFIG_MTD_PHYSMAP_BUSWIDTH=4 + # CONFIG_MTD_PB1000 is not set + # CONFIG_MTD_PB1500 is not set +@@ -193,9 +193,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -214,7 +212,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -304,11 +301,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6452,80 +7313,46 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-hp-lj linux-mips/arch/mips/defconfig- # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -604,7 +596,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_UNIX98_PTYS is not set + + # diff -Nur linux-2.4.29/arch/mips/defconfig-hydrogen3 linux-mips/arch/mips/defconfig-hydrogen3 --- linux-2.4.29/arch/mips/defconfig-hydrogen3 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-hydrogen3 2005-01-31 12:59:29.000000000 +0100 -@@ -22,6 +22,7 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - # CONFIG_MIPS_DB1100 is not set -@@ -30,9 +31,11 @@ ++++ linux-mips/arch/mips/defconfig-hydrogen3 2005-03-26 11:47:15.093174606 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set # CONFIG_MIPS_PB1100 is not set # CONFIG_MIPS_PB1500 is not set -CONFIG_MIPS_HYDROGEN3=y # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +CONFIG_MIPS_HYDROGEN3=y # CONFIG_MIPS_XXS1500 is not set -+# CONFIG_MIPS_EP1000 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set - # CONFIG_BAGET_MIPS is not set -@@ -185,6 +188,7 @@ - CONFIG_MTD_BLOCK=y - # CONFIG_FTL is not set - # CONFIG_NFTL is not set -+# CONFIG_INFTL is not set - - # - # RAM/ROM/Flash chip drivers -@@ -196,6 +200,7 @@ - # CONFIG_MTD_CFI_INTELEXT is not set - CONFIG_MTD_CFI_AMDSTD=y - # CONFIG_MTD_CFI_STAA is not set -+CONFIG_MTD_CFI_UTIL=y - # CONFIG_MTD_RAM is not set - # CONFIG_MTD_ROM is not set - # CONFIG_MTD_ABSENT is not set -@@ -207,17 +212,12 @@ - # - # Mapping drivers for chip access - # -+# CONFIG_MTD_COMPLEX_MAPPINGS is not set - # CONFIG_MTD_PHYSMAP is not set --# CONFIG_MTD_PB1000 is not set --# CONFIG_MTD_PB1500 is not set --# CONFIG_MTD_PB1100 is not set --# CONFIG_MTD_BOSPORUS is not set --# CONFIG_MTD_XXS1500 is not set --# CONFIG_MTD_MTX1 is not set +@@ -214,9 +214,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set -# CONFIG_MTD_DB1X00 is not set # CONFIG_MTD_PB1550 is not set -CONFIG_MTD_HYDROGEN3=y --# CONFIG_MTD_MIRAGE is not set -+# CONFIG_MTD_DB1550 is not set -+# CONFIG_MTD_PB1200 is not set -+# CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MIRAGE is not set # CONFIG_MTD_CSTM_MIPS_IXX is not set # CONFIG_MTD_OCELOT is not set - # CONFIG_MTD_LASAT is not set -@@ -235,9 +235,9 @@ +@@ -235,7 +233,6 @@ # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -+# CONFIG_MTD_DOC2001PLUS is not set # CONFIG_MTD_DOCPROBE is not set - - # -@@ -340,11 +340,6 @@ +@@ -340,11 +337,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6537,23 +7364,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-hydrogen3 linux-mips/arch/mips/defcon # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -386,6 +381,7 @@ - # - # Please see Documentation/ide.txt for help/info on IDE drives - # -+# CONFIG_BLK_DEV_IDE_AU1XXX is not set - # CONFIG_BLK_DEV_HD_IDE is not set - # CONFIG_BLK_DEV_HD is not set - # CONFIG_BLK_DEV_IDE_SATA is not set -@@ -403,6 +399,7 @@ - # - # IDE chipset support/bugfixes - # -+# CONFIG_BLK_DEV_IDE_AU1XXX is not set - # CONFIG_BLK_DEV_CMD640 is not set - # CONFIG_BLK_DEV_CMD640_ENHANCED is not set - # CONFIG_BLK_DEV_ISAPNP is not set -@@ -590,7 +587,6 @@ +@@ -590,7 +582,6 @@ # CONFIG_AU1X00_USB_TTY is not set # CONFIG_AU1X00_USB_RAW is not set # CONFIG_TXX927_SERIAL is not set @@ -6561,34 +7372,15 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-hydrogen3 linux-mips/arch/mips/defcon CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 -@@ -677,6 +673,12 @@ - # CONFIG_SYNCLINK_CS is not set - # CONFIG_AU1X00_GPIO is not set - # CONFIG_TS_AU1X00_ADS7846 is not set -+# CONFIG_AU1550_PSC_SPI is not set -+# CONFIG_AU1XXX_MAE is not set -+# CONFIG_AU1XXX_AES is not set -+# CONFIG_AU1XXX_CIM is not set -+# CONFIG_AU1XXX_AES_TEST is not set -+CONFIG_AU1XXX_BUTTONS=y - - # - # File systems -@@ -838,18 +840,20 @@ +@@ -838,6 +829,7 @@ # CONFIG_FB_PM2 is not set # CONFIG_FB_PM3 is not set # CONFIG_FB_CYBER2000 is not set +CONFIG_FB_AU1100=y -+# CONFIG_FOCUS_ENHANCEMENTS is not set # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set - # CONFIG_FB_ATY128 is not set - # CONFIG_FB_INTEL is not set - # CONFIG_FB_SIS is not set -+# CONFIG_FB_SMI501 is not set - # CONFIG_FB_NEOMAGIC is not set - # CONFIG_FB_3DFX is not set +@@ -849,7 +841,6 @@ # CONFIG_FB_VOODOO1 is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_E1356 is not set @@ -6596,21 +7388,19 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-hydrogen3 linux-mips/arch/mips/defcon # CONFIG_FB_IT8181 is not set # CONFIG_FB_VIRTUAL is not set CONFIG_FBCON_ADVANCED=y -@@ -923,9 +927,11 @@ - # USB Host Controller Drivers - # - # CONFIG_USB_EHCI_HCD is not set -+# CONFIG_USB_NON_PCI_EHCI is not set - # CONFIG_USB_UHCI is not set - # CONFIG_USB_UHCI_ALT is not set - CONFIG_USB_OHCI=y -+CONFIG_USB_NON_PCI_OHCI=y - - # - # USB Device Class drivers diff -Nur linux-2.4.29/arch/mips/defconfig-ip22 linux-mips/arch/mips/defconfig-ip22 --- linux-2.4.29/arch/mips/defconfig-ip22 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ip22 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-ip22 2005-03-26 11:47:15.165162791 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -235,11 +235,6 @@ # # CONFIG_IPX is not set @@ -6623,7 +7413,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ip22 linux-mips/arch/mips/defconfig-i # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -319,6 +314,7 @@ +@@ -319,9 +314,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -6631,10 +7421,61 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ip22 linux-mips/arch/mips/defconfig-i # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -465,7 +462,6 @@ + # CONFIG_SERIAL is not set + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-it8172 linux-mips/arch/mips/defconfig-it8172 --- linux-2.4.29/arch/mips/defconfig-it8172 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-it8172 2005-01-09 20:33:59.000000000 +0100 -@@ -304,11 +304,6 @@ ++++ linux-mips/arch/mips/defconfig-it8172 2005-03-26 11:47:15.242150156 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -186,8 +186,8 @@ + # Mapping drivers for chip access + # + CONFIG_MTD_PHYSMAP=y +-CONFIG_MTD_PHYSMAP_START=8000000 +-CONFIG_MTD_PHYSMAP_LEN=2000000 ++CONFIG_MTD_PHYSMAP_START=0x8000000 ++CONFIG_MTD_PHYSMAP_LEN=0x2000000 + CONFIG_MTD_PHYSMAP_BUSWIDTH=4 + # CONFIG_MTD_PB1000 is not set + # CONFIG_MTD_PB1500 is not set +@@ -195,9 +195,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -216,7 +214,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -304,11 +301,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6646,9 +7487,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-it8172 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -592,7 +584,6 @@ + CONFIG_PC_KEYB=y + # CONFIG_IT8172_SCR0 is not set + # CONFIG_IT8172_SCR1 is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-ivr linux-mips/arch/mips/defconfig-ivr --- linux-2.4.29/arch/mips/defconfig-ivr 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ivr 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-ivr 2005-03-26 11:47:15.318137685 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -226,11 +226,6 @@ # # CONFIG_IPX is not set @@ -6661,9 +7520,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ivr linux-mips/arch/mips/defconfig-iv # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -516,7 +511,6 @@ + CONFIG_QTRONIX_KEYBOARD=y + CONFIG_IT8172_CIR=y + # CONFIG_IT8172_SCR0 is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-jmr3927 linux-mips/arch/mips/defconfig-jmr3927 --- linux-2.4.29/arch/mips/defconfig-jmr3927 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-jmr3927 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-jmr3927 2005-03-26 11:47:15.384126854 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -225,11 +225,6 @@ # # CONFIG_IPX is not set @@ -6676,10 +7553,46 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-jmr3927 linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -454,7 +449,6 @@ + # CONFIG_SERIAL_TXX9_CONSOLE is not set + CONFIG_TXX927_SERIAL=y + CONFIG_TXX927_SERIAL_CONSOLE=y +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_UNIX98_PTYS is not set + + # diff -Nur linux-2.4.29/arch/mips/defconfig-lasat linux-mips/arch/mips/defconfig-lasat --- linux-2.4.29/arch/mips/defconfig-lasat 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-lasat 2005-01-09 20:33:59.000000000 +0100 -@@ -303,11 +303,6 @@ ++++ linux-mips/arch/mips/defconfig-lasat 2005-03-26 11:47:15.455115204 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -198,9 +198,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -219,7 +217,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -303,11 +300,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6691,9 +7604,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-lasat linux-mips/arch/mips/defconfig- # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -584,7 +576,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-malta linux-mips/arch/mips/defconfig-malta --- linux-2.4.29/arch/mips/defconfig-malta 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-malta 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-malta 2005-03-26 11:47:15.526103553 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -237,11 +237,6 @@ # # CONFIG_IPX is not set @@ -6706,7 +7637,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-malta linux-mips/arch/mips/defconfig- # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -319,6 +314,7 @@ +@@ -319,9 +314,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -6714,10 +7645,50 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-malta linux-mips/arch/mips/defconfig- # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -524,7 +521,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-mirage linux-mips/arch/mips/defconfig-mirage --- linux-2.4.29/arch/mips/defconfig-mirage 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-mirage 2005-01-31 12:59:29.000000000 +0100 -@@ -335,11 +335,6 @@ ++++ linux-mips/arch/mips/defconfig-mirage 2005-03-26 11:47:15.615088948 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -209,9 +209,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + CONFIG_MTD_MIRAGE=y + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -230,7 +228,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -335,11 +332,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6729,18 +7700,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-mirage linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -863,7 +858,7 @@ - # CONFIG_USB_UHCI is not set - # CONFIG_USB_UHCI_ALT is not set - CONFIG_USB_OHCI=y -- -+CONFIG_USB_NON_PCI_OHCI=y - # - # USB Device Class drivers - # +@@ -560,7 +552,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-mpc30x linux-mips/arch/mips/defconfig-mpc30x --- linux-2.4.29/arch/mips/defconfig-mpc30x 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-mpc30x 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-mpc30x 2005-03-26 11:47:15.680078282 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -228,11 +228,6 @@ # # CONFIG_IPX is not set @@ -6753,10 +7733,46 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-mpc30x linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -400,7 +395,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-mtx-1 linux-mips/arch/mips/defconfig-mtx-1 --- linux-2.4.29/arch/mips/defconfig-mtx-1 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-mtx-1 2005-01-20 03:19:22.000000000 +0100 -@@ -371,11 +371,6 @@ ++++ linux-mips/arch/mips/defconfig-mtx-1 2005-03-26 11:47:15.793059739 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + CONFIG_MIPS_MTX1=y + # CONFIG_COGENT_CSB250 is not set +@@ -193,9 +193,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + CONFIG_MTD_MTX1=y +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -214,7 +212,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -371,11 +368,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6768,7 +7784,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-mtx-1 linux-mips/arch/mips/defconfig- # CONFIG_DECNET is not set CONFIG_BRIDGE=m # CONFIG_X25 is not set -@@ -479,6 +474,7 @@ +@@ -479,9 +471,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -6776,9 +7792,31 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-mtx-1 linux-mips/arch/mips/defconfig- # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -700,7 +694,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-nino linux-mips/arch/mips/defconfig-nino --- linux-2.4.29/arch/mips/defconfig-nino 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-nino 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-nino 2005-03-26 11:47:15.849050550 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -226,11 +226,6 @@ # # CONFIG_IPX is not set @@ -6791,10 +7829,46 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-nino linux-mips/arch/mips/defconfig-n # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -339,7 +334,6 @@ + # CONFIG_SERIAL_TXX9 is not set + # CONFIG_SERIAL_TXX9_CONSOLE is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_UNIX98_PTYS is not set + + # diff -Nur linux-2.4.29/arch/mips/defconfig-ocelot linux-mips/arch/mips/defconfig-ocelot --- linux-2.4.29/arch/mips/defconfig-ocelot 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ocelot 2005-01-09 20:33:59.000000000 +0100 -@@ -307,11 +307,6 @@ ++++ linux-mips/arch/mips/defconfig-ocelot 2005-03-26 11:47:15.909040704 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -194,9 +194,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + CONFIG_MTD_OCELOT=y +@@ -215,7 +213,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + CONFIG_MTD_DOC2000=y + # CONFIG_MTD_DOC2001 is not set + CONFIG_MTD_DOCPROBE=y +@@ -307,11 +304,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6806,9 +7880,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ocelot linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -513,7 +505,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-osprey linux-mips/arch/mips/defconfig-osprey --- linux-2.4.29/arch/mips/defconfig-osprey 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-osprey 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-osprey 2005-03-26 11:47:15.963031843 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -227,11 +227,6 @@ # # CONFIG_IPX is not set @@ -6821,31 +7913,46 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-osprey linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -388,7 +383,6 @@ + # CONFIG_SERIAL_MULTIPORT is not set + # CONFIG_HUB6 is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-pb1000 linux-mips/arch/mips/defconfig-pb1000 --- linux-2.4.29/arch/mips/defconfig-pb1000 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-pb1000 2005-02-12 04:05:27.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - # CONFIG_MIPS_DB1100 is not set - # CONFIG_MIPS_DB1500 is not set - # CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-pb1000 2005-03-26 11:47:16.057016418 +0100 +@@ -30,8 +30,8 @@ CONFIG_MIPS_PB1000=y # CONFIG_MIPS_PB1100 is not set # CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -324,11 +327,6 @@ +@@ -215,9 +215,7 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -236,7 +234,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -324,11 +321,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6857,7 +7964,15 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1000 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -707,7 +705,7 @@ +@@ -622,7 +614,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + +@@ -707,7 +698,7 @@ # # CONFIG_PCMCIA_SERIAL_CS is not set # CONFIG_SYNCLINK_CS is not set @@ -6868,29 +7983,36 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1000 linux-mips/arch/mips/defconfig # diff -Nur linux-2.4.29/arch/mips/defconfig-pb1100 linux-mips/arch/mips/defconfig-pb1100 --- linux-2.4.29/arch/mips/defconfig-pb1100 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-pb1100 2005-02-12 04:05:28.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - # CONFIG_MIPS_DB1100 is not set - # CONFIG_MIPS_DB1500 is not set - # CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-pb1100 2005-03-26 11:47:16.158999680 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set CONFIG_MIPS_PB1100=y # CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -324,11 +327,6 @@ +@@ -198,9 +198,7 @@ + # CONFIG_MTD_MTX1 is not set + CONFIG_MTD_PB1500_BOOT=y + CONFIG_MTD_PB1500_USER=y +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -219,7 +217,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -324,11 +321,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -6902,10 +8024,34 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1100 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -613,7 +605,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + +@@ -859,6 +850,7 @@ + # CONFIG_FB_PM2 is not set + # CONFIG_FB_PM3 is not set + # CONFIG_FB_CYBER2000 is not set ++CONFIG_FB_AU1100=y + # CONFIG_FB_MATROX is not set + # CONFIG_FB_ATY is not set + # CONFIG_FB_RADEON is not set +@@ -870,7 +862,6 @@ + # CONFIG_FB_VOODOO1 is not set + # CONFIG_FB_TRIDENT is not set + # CONFIG_FB_E1356 is not set +-CONFIG_FB_AU1100=y + # CONFIG_FB_IT8181 is not set + # CONFIG_FB_VIRTUAL is not set + CONFIG_FBCON_ADVANCED=y diff -Nur linux-2.4.29/arch/mips/defconfig-pb1200 linux-mips/arch/mips/defconfig-pb1200 --- linux-2.4.29/arch/mips/defconfig-pb1200 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-pb1200 2005-01-30 09:01:27.000000000 +0100 -@@ -0,0 +1,1063 @@ ++++ linux-mips/arch/mips/defconfig-pb1200 2005-03-26 11:47:16.258983270 +0100 +@@ -0,0 +1,1060 @@ +# +# Automatically generated make config: don't edit +# @@ -6930,18 +8076,15 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1200 linux-mips/arch/mips/defconfig +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set -+CONFIG_MIPS_PB1200=y +# CONFIG_MIPS_HYDROGEN3 is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set @@ -7299,6 +8442,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1200 linux-mips/arch/mips/defconfig +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set @@ -7512,7 +8656,6 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1200 linux-mips/arch/mips/defconfig +# CONFIG_AU1X00_USB_TTY is not set +# CONFIG_AU1X00_USB_RAW is not set +# CONFIG_TXX927_SERIAL is not set -+# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + @@ -7971,29 +9114,36 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1200 linux-mips/arch/mips/defconfig +# CONFIG_FW_LOADER is not set diff -Nur linux-2.4.29/arch/mips/defconfig-pb1500 linux-mips/arch/mips/defconfig-pb1500 --- linux-2.4.29/arch/mips/defconfig-pb1500 2005-01-19 15:09:28.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-pb1500 2005-02-12 04:05:28.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - # CONFIG_MIPS_DB1100 is not set - # CONFIG_MIPS_DB1500 is not set - # CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-pb1500 2005-03-26 11:47:16.365965712 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set # CONFIG_MIPS_PB1100 is not set CONFIG_MIPS_PB1500=y -# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_PB1550 is not set -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -341,11 +344,6 @@ +@@ -215,9 +215,7 @@ + # CONFIG_MTD_MTX1 is not set + CONFIG_MTD_PB1500_BOOT=y + # CONFIG_MTD_PB1500_USER is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -236,7 +234,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -341,11 +338,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -8005,31 +9155,48 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1500 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -675,7 +667,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-pb1550 linux-mips/arch/mips/defconfig-pb1550 --- linux-2.4.29/arch/mips/defconfig-pb1550 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-pb1550 2005-02-12 04:05:28.000000000 +0100 -@@ -22,16 +22,19 @@ - # - # CONFIG_ACER_PICA_61 is not set - # CONFIG_MIPS_BOSPORUS is not set -+# CONFIG_MIPS_FICMMP is not set - # CONFIG_MIPS_MIRAGE is not set - # CONFIG_MIPS_DB1000 is not set - # CONFIG_MIPS_DB1100 is not set - # CONFIG_MIPS_DB1500 is not set - # CONFIG_MIPS_DB1550 is not set -+# CONFIG_MIPS_DB1200 is not set ++++ linux-mips/arch/mips/defconfig-pb1550 2005-03-26 11:47:16.471948318 +0100 +@@ -30,8 +30,8 @@ # CONFIG_MIPS_PB1000 is not set # CONFIG_MIPS_PB1100 is not set # CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_HYDROGEN3 is not set CONFIG_MIPS_PB1550=y -+# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_HYDROGEN3 is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_MIPS_MTX1 is not set # CONFIG_COGENT_CSB250 is not set -@@ -343,11 +346,6 @@ +@@ -213,11 +213,9 @@ + # CONFIG_MTD_BOSPORUS is not set + # CONFIG_MTD_XXS1500 is not set + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + CONFIG_MTD_PB1550=y + CONFIG_MTD_PB1550_BOOT=y + CONFIG_MTD_PB1550_USER=y +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -236,7 +234,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -343,11 +340,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -8041,9 +9208,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-pb1550 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -633,7 +625,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-rbtx4927 linux-mips/arch/mips/defconfig-rbtx4927 --- linux-2.4.29/arch/mips/defconfig-rbtx4927 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-rbtx4927 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-rbtx4927 2005-03-26 11:47:16.531938472 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -223,11 +223,6 @@ # # CONFIG_IPX is not set @@ -8056,9 +9241,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-rbtx4927 linux-mips/arch/mips/defconf # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -466,7 +461,6 @@ + CONFIG_SERIAL_TXX9=y + CONFIG_SERIAL_TXX9_CONSOLE=y + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_UNIX98_PTYS is not set + + # diff -Nur linux-2.4.29/arch/mips/defconfig-rm200 linux-mips/arch/mips/defconfig-rm200 --- linux-2.4.29/arch/mips/defconfig-rm200 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-rm200 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-rm200 2005-03-26 11:47:16.579930595 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -229,11 +229,6 @@ # # CONFIG_IPX is not set @@ -8071,9 +9274,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-rm200 linux-mips/arch/mips/defconfig- # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -340,7 +335,6 @@ + # CONFIG_SERIAL is not set + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-sb1250-swarm linux-mips/arch/mips/defconfig-sb1250-swarm --- linux-2.4.29/arch/mips/defconfig-sb1250-swarm 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-sb1250-swarm 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-sb1250-swarm 2005-03-26 11:47:16.645919765 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -90,6 +90,7 @@ # CONFIG_SIBYTE_TBPROF is not set CONFIG_SIBYTE_GENBUS_IDE=y @@ -8094,9 +9315,48 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-sb1250-swarm linux-mips/arch/mips/def # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -469,7 +465,6 @@ + CONFIG_SIBYTE_SB1250_DUART=y + CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y + CONFIG_SERIAL_CONSOLE=y +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + +diff -Nur linux-2.4.29/arch/mips/defconfig-sead linux-mips/arch/mips/defconfig-sead +--- linux-2.4.29/arch/mips/defconfig-sead 2005-01-19 15:09:29.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-sead 2005-03-26 11:47:16.686913037 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -244,7 +244,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_UNIX98_PTYS is not set + + # diff -Nur linux-2.4.29/arch/mips/defconfig-stretch linux-mips/arch/mips/defconfig-stretch --- linux-2.4.29/arch/mips/defconfig-stretch 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-stretch 2005-01-09 20:33:59.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-stretch 2005-03-26 11:47:16.751902371 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -240,11 +240,6 @@ # # CONFIG_IPX is not set @@ -8109,7 +9369,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-stretch linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -324,6 +319,7 @@ +@@ -324,9 +319,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -8117,9 +9377,31 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-stretch linux-mips/arch/mips/defconfi # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -516,7 +513,6 @@ + # CONFIG_SERIAL_TXX9 is not set + # CONFIG_SERIAL_TXX9_CONSOLE is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-tb0226 linux-mips/arch/mips/defconfig-tb0226 --- linux-2.4.29/arch/mips/defconfig-tb0226 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-tb0226 2005-01-09 20:34:00.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-tb0226 2005-03-26 11:47:16.828889735 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -228,11 +228,6 @@ # # CONFIG_IPX is not set @@ -8132,7 +9414,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-tb0226 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -312,6 +307,7 @@ +@@ -312,9 +307,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -8140,9 +9422,31 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-tb0226 linux-mips/arch/mips/defconfig # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -518,7 +515,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-tb0229 linux-mips/arch/mips/defconfig-tb0229 --- linux-2.4.29/arch/mips/defconfig-tb0229 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-tb0229 2005-01-09 20:34:00.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-tb0229 2005-03-26 11:47:16.893879069 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -230,11 +230,6 @@ # # CONFIG_IPX is not set @@ -8155,10 +9459,46 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-tb0229 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -445,7 +440,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-ti1500 linux-mips/arch/mips/defconfig-ti1500 --- linux-2.4.29/arch/mips/defconfig-ti1500 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-ti1500 2005-01-09 20:34:00.000000000 +0100 -@@ -339,11 +339,6 @@ ++++ linux-mips/arch/mips/defconfig-ti1500 2005-03-26 11:47:16.995862331 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + CONFIG_MIPS_XXS1500=y + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -213,9 +213,7 @@ + # CONFIG_MTD_BOSPORUS is not set + CONFIG_MTD_XXS1500=y + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -234,7 +232,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -339,11 +336,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -8170,9 +9510,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-ti1500 linux-mips/arch/mips/defconfig # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -600,7 +592,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-workpad linux-mips/arch/mips/defconfig-workpad --- linux-2.4.29/arch/mips/defconfig-workpad 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-workpad 2005-01-09 20:34:00.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-workpad 2005-03-26 11:47:17.054852650 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -222,11 +222,6 @@ # # CONFIG_IPX is not set @@ -8185,10 +9543,46 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-workpad linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -426,7 +421,6 @@ + # CONFIG_SERIAL_MULTIPORT is not set + # CONFIG_HUB6 is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_VR41XX_KIU is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 diff -Nur linux-2.4.29/arch/mips/defconfig-xxs1500 linux-mips/arch/mips/defconfig-xxs1500 --- linux-2.4.29/arch/mips/defconfig-xxs1500 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-xxs1500 2005-01-09 20:34:00.000000000 +0100 -@@ -339,11 +339,6 @@ ++++ linux-mips/arch/mips/defconfig-xxs1500 2005-03-26 11:47:17.143838045 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + CONFIG_MIPS_XXS1500=y + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -213,9 +213,7 @@ + # CONFIG_MTD_BOSPORUS is not set + CONFIG_MTD_XXS1500=y + # CONFIG_MTD_MTX1 is not set +-# CONFIG_MTD_DB1X00 is not set + # CONFIG_MTD_PB1550 is not set +-# CONFIG_MTD_HYDROGEN3 is not set + # CONFIG_MTD_MIRAGE is not set + # CONFIG_MTD_CSTM_MIPS_IXX is not set + # CONFIG_MTD_OCELOT is not set +@@ -234,7 +232,6 @@ + # + # Disk-On-Chip Device Drivers + # +-# CONFIG_MTD_DOC1000 is not set + # CONFIG_MTD_DOC2000 is not set + # CONFIG_MTD_DOC2001 is not set + # CONFIG_MTD_DOCPROBE is not set +@@ -339,11 +336,6 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -8200,9 +9594,27 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-xxs1500 linux-mips/arch/mips/defconfi # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -671,7 +663,6 @@ + # CONFIG_AU1X00_USB_TTY is not set + # CONFIG_AU1X00_USB_RAW is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/defconfig-yosemite linux-mips/arch/mips/defconfig-yosemite --- linux-2.4.29/arch/mips/defconfig-yosemite 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/defconfig-yosemite 2005-01-09 20:34:00.000000000 +0100 ++++ linux-mips/arch/mips/defconfig-yosemite 2005-03-26 11:47:17.208827379 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -227,11 +227,6 @@ # # CONFIG_IPX is not set @@ -8215,7 +9627,7 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-yosemite linux-mips/arch/mips/defconf # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -310,6 +305,7 @@ +@@ -310,9 +305,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -8223,6 +9635,18 @@ diff -Nur linux-2.4.29/arch/mips/defconfig-yosemite linux-mips/arch/mips/defconf # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -477,7 +474,6 @@ + # CONFIG_SERIAL_TXX9 is not set + # CONFIG_SERIAL_TXX9_CONSOLE is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips/kernel/cpu-probe.c linux-mips/arch/mips/kernel/cpu-probe.c --- linux-2.4.29/arch/mips/kernel/cpu-probe.c 2005-01-19 15:09:29.000000000 +0100 +++ linux-mips/arch/mips/kernel/cpu-probe.c 2005-01-31 12:59:30.000000000 +0100 @@ -8407,7 +9831,7 @@ diff -Nur linux-2.4.29/arch/mips/kernel/head.S linux-mips/arch/mips/kernel/head. diff -Nur linux-2.4.29/arch/mips/kernel/scall_o32.S linux-mips/arch/mips/kernel/scall_o32.S --- linux-2.4.29/arch/mips/kernel/scall_o32.S 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/kernel/scall_o32.S 2005-02-12 04:05:33.000000000 +0100 ++++ linux-mips/arch/mips/kernel/scall_o32.S 2005-03-26 11:47:17.566768632 +0100 @@ -121,15 +121,14 @@ trace_a_syscall: @@ -8555,39 +9979,76 @@ diff -Nur linux-2.4.29/arch/mips/lib/rtc-std.c linux-mips/arch/mips/lib/rtc-std. }; - -EXPORT_SYMBOL(rtc_ops); -diff -Nur linux-2.4.29/arch/mips/mm/c-r4k.c linux-mips/arch/mips/mm/c-r4k.c ---- linux-2.4.29/arch/mips/mm/c-r4k.c 2005-01-19 15:09:29.000000000 +0100 -+++ linux-mips/arch/mips/mm/c-r4k.c 2005-02-12 04:05:35.000000000 +0100 -@@ -867,9 +867,16 @@ - * normally they'd suffer from aliases but magic in the hardware deals - * with that for us so we don't need to take care ourselves. - */ -- if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000) -- if (c->dcache.waysize > PAGE_SIZE) -- c->dcache.flags |= MIPS_CACHE_ALIASES; -+ switch (c->cputype) { -+ case CPU_R10000: -+ case CPU_R12000: -+ break; -+ case CPU_24K: -+ if (!(read_c0_config7() & (1 << 16))) -+ default: -+ if (c->dcache.waysize > PAGE_SIZE) -+ c->dcache.flags |= MIPS_CACHE_ALIASES; -+ } +diff -Nur linux-2.4.29/arch/mips/Makefile linux-mips/arch/mips/Makefile +--- linux-2.4.29/arch/mips/Makefile 2005-01-19 15:09:26.000000000 +0100 ++++ linux-mips/arch/mips/Makefile 2005-01-31 12:59:28.000000000 +0100 +@@ -211,7 +211,7 @@ + endif - switch (c->cputype) { - case CPU_20KC: -@@ -1069,9 +1076,6 @@ - probe_pcache(); - setup_scache(); + # +-# Au1000 (Alchemy Semi PB1000) eval board ++# Au1x AMD Alchemy eval boards + # + ifdef CONFIG_MIPS_PB1000 + LIBS += arch/mips/au1000/pb1000/pb1000.o \ +@@ -220,9 +220,6 @@ + LOADADDR := 0x80100000 + endif -- if (c->dcache.sets * c->dcache.ways > PAGE_SIZE) -- c->dcache.flags |= MIPS_CACHE_ALIASES; -- - r4k_blast_dcache_page_setup(); - r4k_blast_dcache_page_indexed_setup(); - r4k_blast_dcache_setup(); +-# +-# Au1100 (Alchemy Semi PB1100) eval board +-# + ifdef CONFIG_MIPS_PB1100 + LIBS += arch/mips/au1000/pb1100/pb1100.o \ + arch/mips/au1000/common/au1000.o +@@ -230,9 +227,6 @@ + LOADADDR += 0x80100000 + endif + +-# +-# Au1500 (Alchemy Semi PB1500) eval board +-# + ifdef CONFIG_MIPS_PB1500 + LIBS += arch/mips/au1000/pb1500/pb1500.o \ + arch/mips/au1000/common/au1000.o +@@ -240,9 +234,6 @@ + LOADADDR := 0x80100000 + endif + +-# +-# Au1x00 (AMD/Alchemy) eval boards +-# + ifdef CONFIG_MIPS_DB1000 + LIBS += arch/mips/au1000/db1x00/db1x00.o \ + arch/mips/au1000/common/au1000.o +@@ -313,6 +304,27 @@ + LOADADDR += 0x80100000 + endif + ++ifdef CONFIG_MIPS_PB1200 ++LIBS += arch/mips/au1000/pb1200/pb1200.o \ ++ arch/mips/au1000/common/au1000.o ++SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common ++LOADADDR += 0x80100000 ++endif ++ ++ifdef CONFIG_MIPS_DB1200 ++LIBS += arch/mips/au1000/pb1200/pb1200.o \ ++ arch/mips/au1000/common/au1000.o ++SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common ++LOADADDR += 0x80100000 ++endif ++ ++ifdef CONFIG_MIPS_FICMMP ++LIBS += arch/mips/au1000/ficmmp/ficmmp.o \ ++ arch/mips/au1000/common/au1000.o ++SUBDIRS += arch/mips/au1000/ficmmp arch/mips/au1000/common ++LOADADDR += 0x80100000 ++endif ++ + + # + # Cogent CSB250 diff -Nur linux-2.4.29/arch/mips/mm/cerr-sb1.c linux-mips/arch/mips/mm/cerr-sb1.c --- linux-2.4.29/arch/mips/mm/cerr-sb1.c 2004-02-18 14:36:30.000000000 +0100 +++ linux-mips/arch/mips/mm/cerr-sb1.c 2004-12-13 18:37:23.000000000 +0100 @@ -8635,6 +10096,122 @@ diff -Nur linux-2.4.29/arch/mips/mm/cerr-sb1.c linux-mips/arch/mips/mm/cerr-sb1. if (way == 0) { lru = (taghi >> 14) & 0xff; prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n", +diff -Nur linux-2.4.29/arch/mips/mm/c-r4k.c linux-mips/arch/mips/mm/c-r4k.c +--- linux-2.4.29/arch/mips/mm/c-r4k.c 2005-01-19 15:09:29.000000000 +0100 ++++ linux-mips/arch/mips/mm/c-r4k.c 2005-03-26 11:47:17.585765515 +0100 +@@ -867,9 +867,16 @@ + * normally they'd suffer from aliases but magic in the hardware deals + * with that for us so we don't need to take care ourselves. + */ +- if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000) +- if (c->dcache.waysize > PAGE_SIZE) +- c->dcache.flags |= MIPS_CACHE_ALIASES; ++ switch (c->cputype) { ++ case CPU_R10000: ++ case CPU_R12000: ++ break; ++ case CPU_24K: ++ if (!(read_c0_config7() & (1 << 16))) ++ default: ++ if (c->dcache.waysize > PAGE_SIZE) ++ c->dcache.flags |= MIPS_CACHE_ALIASES; ++ } + + switch (c->cputype) { + case CPU_20KC: +@@ -1069,9 +1076,6 @@ + probe_pcache(); + setup_scache(); + +- if (c->dcache.sets * c->dcache.ways > PAGE_SIZE) +- c->dcache.flags |= MIPS_CACHE_ALIASES; +- + r4k_blast_dcache_page_setup(); + r4k_blast_dcache_page_indexed_setup(); + r4k_blast_dcache_setup(); +diff -Nur linux-2.4.29/arch/mips/mm/tlbex-mips32.S linux-mips/arch/mips/mm/tlbex-mips32.S +--- linux-2.4.29/arch/mips/mm/tlbex-mips32.S 2004-02-18 14:36:30.000000000 +0100 ++++ linux-mips/arch/mips/mm/tlbex-mips32.S 2004-11-29 00:33:15.000000000 +0100 +@@ -196,7 +196,7 @@ + .set noat; \ + SAVE_ALL; \ + mfc0 a2, CP0_BADVADDR; \ +- STI; \ ++ KMODE; \ + .set at; \ + move a0, sp; \ + jal do_page_fault; \ +diff -Nur linux-2.4.29/arch/mips/mm/tlbex-r4k.S linux-mips/arch/mips/mm/tlbex-r4k.S +--- linux-2.4.29/arch/mips/mm/tlbex-r4k.S 2004-02-18 14:36:30.000000000 +0100 ++++ linux-mips/arch/mips/mm/tlbex-r4k.S 2004-11-25 23:18:38.000000000 +0100 +@@ -184,13 +184,10 @@ + P_MTC0 k0, CP0_ENTRYLO0 # load it + PTE_SRL k1, k1, 6 # convert to entrylo1 + P_MTC0 k1, CP0_ENTRYLO1 # load it +- b 1f +- rm9000_tlb_hazard ++ mtc0_tlbw_hazard + tlbwr # write random tlb entry +-1: +- nop +- rm9000_tlb_hazard +- eret # return from trap ++ tlbw_eret_hazard ++ eret + END(except_vec0_r4000) + + /* TLB refill, EXL == 0, R4600 version */ +@@ -468,13 +465,10 @@ + PTE_PRESENT(k0, k1, nopage_tlbl) + PTE_MAKEVALID(k0, k1) + PTE_RELOAD(k1, k0) +- rm9000_tlb_hazard +- nop +- b 1f +- tlbwi +-1: ++ mtc0_tlbw_hazard ++ tlbwi + nop +- rm9000_tlb_hazard ++ tlbw_eret_hazard + .set mips3 + eret + .set mips0 +@@ -496,13 +490,10 @@ + PTE_WRITABLE(k0, k1, nopage_tlbs) + PTE_MAKEWRITE(k0, k1) + PTE_RELOAD(k1, k0) +- rm9000_tlb_hazard +- nop +- b 1f +- tlbwi +-1: ++ mtc0_tlbw_hazard ++ tlbwi + nop +- rm9000_tlb_hazard ++ tlbw_eret_hazard + .set mips3 + eret + .set mips0 +@@ -529,13 +520,10 @@ + + /* Now reload the entry into the tlb. */ + PTE_RELOAD(k1, k0) +- rm9000_tlb_hazard +- nop +- b 1f +- tlbwi +-1: +- rm9000_tlb_hazard ++ mtc0_tlbw_hazard ++ tlbwi + nop ++ tlbw_eret_hazard + .set mips3 + eret + .set mips0 diff -Nur linux-2.4.29/arch/mips/mm/tlb-r4k.c linux-mips/arch/mips/mm/tlb-r4k.c --- linux-2.4.29/arch/mips/mm/tlb-r4k.c 2005-01-19 15:09:29.000000000 +0100 +++ linux-mips/arch/mips/mm/tlb-r4k.c 2004-11-25 23:18:38.000000000 +0100 @@ -8964,93 +10541,20 @@ diff -Nur linux-2.4.29/arch/mips/mm/tlb-r4k.c linux-mips/arch/mips/mm/tlb-r4k.c /* * You should never change this register: -diff -Nur linux-2.4.29/arch/mips/mm/tlbex-mips32.S linux-mips/arch/mips/mm/tlbex-mips32.S ---- linux-2.4.29/arch/mips/mm/tlbex-mips32.S 2004-02-18 14:36:30.000000000 +0100 -+++ linux-mips/arch/mips/mm/tlbex-mips32.S 2004-11-29 00:33:15.000000000 +0100 -@@ -196,7 +196,7 @@ - .set noat; \ - SAVE_ALL; \ - mfc0 a2, CP0_BADVADDR; \ -- STI; \ -+ KMODE; \ - .set at; \ - move a0, sp; \ - jal do_page_fault; \ -diff -Nur linux-2.4.29/arch/mips/mm/tlbex-r4k.S linux-mips/arch/mips/mm/tlbex-r4k.S ---- linux-2.4.29/arch/mips/mm/tlbex-r4k.S 2004-02-18 14:36:30.000000000 +0100 -+++ linux-mips/arch/mips/mm/tlbex-r4k.S 2004-11-25 23:18:38.000000000 +0100 -@@ -184,13 +184,10 @@ - P_MTC0 k0, CP0_ENTRYLO0 # load it - PTE_SRL k1, k1, 6 # convert to entrylo1 - P_MTC0 k1, CP0_ENTRYLO1 # load it -- b 1f -- rm9000_tlb_hazard -+ mtc0_tlbw_hazard - tlbwr # write random tlb entry --1: -- nop -- rm9000_tlb_hazard -- eret # return from trap -+ tlbw_eret_hazard -+ eret - END(except_vec0_r4000) - - /* TLB refill, EXL == 0, R4600 version */ -@@ -468,13 +465,10 @@ - PTE_PRESENT(k0, k1, nopage_tlbl) - PTE_MAKEVALID(k0, k1) - PTE_RELOAD(k1, k0) -- rm9000_tlb_hazard -- nop -- b 1f -- tlbwi --1: -+ mtc0_tlbw_hazard -+ tlbwi - nop -- rm9000_tlb_hazard -+ tlbw_eret_hazard - .set mips3 - eret - .set mips0 -@@ -496,13 +490,10 @@ - PTE_WRITABLE(k0, k1, nopage_tlbs) - PTE_MAKEWRITE(k0, k1) - PTE_RELOAD(k1, k0) -- rm9000_tlb_hazard -- nop -- b 1f -- tlbwi --1: -+ mtc0_tlbw_hazard -+ tlbwi - nop -- rm9000_tlb_hazard -+ tlbw_eret_hazard - .set mips3 - eret - .set mips0 -@@ -529,13 +520,10 @@ - - /* Now reload the entry into the tlb. */ - PTE_RELOAD(k1, k0) -- rm9000_tlb_hazard -- nop -- b 1f -- tlbwi --1: -- rm9000_tlb_hazard -+ mtc0_tlbw_hazard -+ tlbwi - nop -+ tlbw_eret_hazard - .set mips3 - eret - .set mips0 diff -Nur linux-2.4.29/arch/mips64/defconfig linux-mips/arch/mips64/defconfig --- linux-2.4.29/arch/mips64/defconfig 2005-01-19 15:09:30.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig 2005-01-20 03:19:22.000000000 +0100 -@@ -470,6 +470,7 @@ ++++ linux-mips/arch/mips64/defconfig 2005-03-26 11:47:17.749738603 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -470,9 +470,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -9058,9 +10562,31 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig linux-mips/arch/mips64/defconfig # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -658,7 +660,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-atlas linux-mips/arch/mips64/defconfig-atlas --- linux-2.4.29/arch/mips64/defconfig-atlas 2005-01-19 15:09:30.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-atlas 2005-01-09 20:34:01.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-atlas 2005-03-26 11:47:17.816727608 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -232,11 +232,6 @@ # # CONFIG_IPX is not set @@ -9073,7 +10599,7 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-atlas linux-mips/arch/mips64/defcon # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -314,6 +309,7 @@ +@@ -314,9 +309,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -9081,9 +10607,31 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-atlas linux-mips/arch/mips64/defcon # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -474,7 +471,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-decstation linux-mips/arch/mips64/defconfig-decstation --- linux-2.4.29/arch/mips64/defconfig-decstation 2005-01-19 15:09:30.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-decstation 2005-01-09 20:34:01.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-decstation 2005-03-26 11:47:17.884716450 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -224,11 +224,6 @@ # # CONFIG_IPX is not set @@ -9096,7 +10644,7 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-decstation linux-mips/arch/mips64/d # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -307,6 +302,7 @@ +@@ -307,9 +302,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -9104,9 +10652,31 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-decstation linux-mips/arch/mips64/d # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -477,7 +474,6 @@ + CONFIG_SERIAL_DEC_CONSOLE=y + # CONFIG_DZ is not set + CONFIG_ZS=y +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-ip22 linux-mips/arch/mips64/defconfig-ip22 --- linux-2.4.29/arch/mips64/defconfig-ip22 2005-01-19 15:09:31.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-ip22 2005-01-09 20:34:01.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-ip22 2005-03-26 11:47:17.955704799 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -235,11 +235,6 @@ # # CONFIG_IPX is not set @@ -9119,7 +10689,7 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-ip22 linux-mips/arch/mips64/defconf # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -319,6 +314,7 @@ +@@ -319,9 +314,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -9127,10 +10697,32 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-ip22 linux-mips/arch/mips64/defconf # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -488,7 +485,6 @@ + # CONFIG_SERIAL_TXX9_CONSOLE is not set + # CONFIG_TXX927_SERIAL is not set + CONFIG_IP22_SERIAL=y +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-ip27 linux-mips/arch/mips64/defconfig-ip27 --- linux-2.4.29/arch/mips64/defconfig-ip27 2005-01-19 15:09:31.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-ip27 2005-01-20 03:19:22.000000000 +0100 -@@ -470,6 +470,7 @@ ++++ linux-mips/arch/mips64/defconfig-ip27 2005-03-26 11:47:18.038691179 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -470,9 +470,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -9138,9 +10730,31 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-ip27 linux-mips/arch/mips64/defconf # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -658,7 +660,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-jaguar linux-mips/arch/mips64/defconfig-jaguar --- linux-2.4.29/arch/mips64/defconfig-jaguar 2005-01-19 15:09:31.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-jaguar 2005-01-09 20:34:01.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-jaguar 2005-03-26 11:47:18.091682482 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -227,11 +227,6 @@ # # CONFIG_IPX is not set @@ -9153,9 +10767,27 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-jaguar linux-mips/arch/mips64/defco # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -403,7 +398,6 @@ + # CONFIG_SERIAL_TXX9 is not set + # CONFIG_SERIAL_TXX9_CONSOLE is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-malta linux-mips/arch/mips64/defconfig-malta --- linux-2.4.29/arch/mips64/defconfig-malta 2005-01-19 15:09:31.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-malta 2005-01-09 20:34:01.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-malta 2005-03-26 11:47:18.150672800 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -235,11 +235,6 @@ # # CONFIG_IPX is not set @@ -9168,7 +10800,7 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-malta linux-mips/arch/mips64/defcon # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set -@@ -317,6 +312,7 @@ +@@ -317,9 +312,11 @@ # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_MEGARAID2 is not set # CONFIG_SCSI_SATA is not set @@ -9176,9 +10808,31 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-malta linux-mips/arch/mips64/defcon # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set ++# CONFIG_SCSI_SATA_QSTOR is not set + # CONFIG_SCSI_SATA_PROMISE is not set + # CONFIG_SCSI_SATA_SX4 is not set + # CONFIG_SCSI_SATA_SIL is not set +@@ -477,7 +474,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-ocelotc linux-mips/arch/mips64/defconfig-ocelotc --- linux-2.4.29/arch/mips64/defconfig-ocelotc 2005-01-19 15:09:31.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-ocelotc 2005-01-09 20:34:01.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-ocelotc 2005-03-26 11:47:18.209663119 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -231,11 +231,6 @@ # # CONFIG_IPX is not set @@ -9191,9 +10845,27 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-ocelotc linux-mips/arch/mips64/defc # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -453,7 +448,6 @@ + # CONFIG_SERIAL_TXX9 is not set + # CONFIG_SERIAL_TXX9_CONSOLE is not set + # CONFIG_TXX927_SERIAL is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + diff -Nur linux-2.4.29/arch/mips64/defconfig-sb1250-swarm linux-mips/arch/mips64/defconfig-sb1250-swarm --- linux-2.4.29/arch/mips64/defconfig-sb1250-swarm 2005-01-19 15:09:31.000000000 +0100 -+++ linux-mips/arch/mips64/defconfig-sb1250-swarm 2005-01-09 20:34:01.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-sb1250-swarm 2005-03-26 11:47:18.269653273 +0100 +@@ -30,8 +30,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set @@ -90,6 +90,7 @@ # CONFIG_SIBYTE_TBPROF is not set CONFIG_SIBYTE_GENBUS_IDE=y @@ -9214,6 +10886,35 @@ diff -Nur linux-2.4.29/arch/mips64/defconfig-sb1250-swarm linux-mips/arch/mips64 # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set +@@ -432,7 +428,6 @@ + CONFIG_SIBYTE_SB1250_DUART=y + CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y + CONFIG_SERIAL_CONSOLE=y +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + CONFIG_UNIX98_PTYS=y + CONFIG_UNIX98_PTY_COUNT=256 + +diff -Nur linux-2.4.29/arch/mips64/defconfig-sead linux-mips/arch/mips64/defconfig-sead +--- linux-2.4.29/arch/mips64/defconfig-sead 2005-01-19 15:09:31.000000000 +0100 ++++ linux-mips/arch/mips64/defconfig-sead 2005-03-26 11:47:18.311646381 +0100 +@@ -28,8 +28,8 @@ + # CONFIG_MIPS_PB1000 is not set + # CONFIG_MIPS_PB1100 is not set + # CONFIG_MIPS_PB1500 is not set +-# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_PB1550 is not set ++# CONFIG_MIPS_HYDROGEN3 is not set + # CONFIG_MIPS_XXS1500 is not set + # CONFIG_MIPS_MTX1 is not set + # CONFIG_COGENT_CSB250 is not set +@@ -242,7 +242,6 @@ + CONFIG_SERIAL_CONSOLE=y + # CONFIG_SERIAL_EXTENDED is not set + # CONFIG_SERIAL_NONSTANDARD is not set +-# CONFIG_MIPS_HYDROGEN3_BUTTONS is not set + # CONFIG_UNIX98_PTYS is not set + + # diff -Nur linux-2.4.29/arch/mips64/kernel/binfmt_elfn32.c linux-mips/arch/mips64/kernel/binfmt_elfn32.c --- linux-2.4.29/arch/mips64/kernel/binfmt_elfn32.c 2003-08-25 13:44:40.000000000 +0200 +++ linux-mips/arch/mips64/kernel/binfmt_elfn32.c 2005-01-31 12:59:30.000000000 +0100 @@ -9335,9 +11036,150 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/ioctl32.c linux-mips/arch/mips64/kerne IOCTL32_DEFAULT(AUTOFS_IOC_ASKREGHOST), IOCTL32_DEFAULT(AUTOFS_IOC_TOGGLEREGHOST), IOCTL32_DEFAULT(AUTOFS_IOC_ASKUMOUNT), +diff -Nur linux-2.4.29/arch/mips64/kernel/linux32.c linux-mips/arch/mips64/kernel/linux32.c +--- linux-2.4.29/arch/mips64/kernel/linux32.c 2005-01-19 15:09:32.000000000 +0100 ++++ linux-mips/arch/mips64/kernel/linux32.c 2005-03-26 11:47:18.669587634 +0100 +@@ -1088,11 +1088,9 @@ + i--; + } + +- inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ +- retval = locks_verify_area((type == VERIFY_WRITE +- ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), +- inode, file, file->f_pos, tot_len); ++ retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE), ++ file, &file->f_pos, tot_len); + if (retval) { + if (iov != iovstack) + kfree(iov); +@@ -1189,72 +1187,19 @@ + lseek back to original location. They fail just like lseek does on + non-seekable files. */ + +-asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, +- size_t count, u32 unused, u64 a4, u64 a5) ++asmlinkage ssize_t sys32_pread(unsigned int fd, char *buf, ++ size_t count, u32 unused, u64 a4, u64 a5) + { +- ssize_t ret; +- struct file * file; +- ssize_t (*read)(struct file *, char *, size_t, loff_t *); +- loff_t pos; +- +- ret = -EBADF; +- file = fget(fd); +- if (!file) +- goto bad_file; +- if (!(file->f_mode & FMODE_READ)) +- goto out; +- pos = merge_64(a4, a5); +- ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, +- file, pos, count); +- if (ret) +- goto out; +- ret = -EINVAL; +- if (!file->f_op || !(read = file->f_op->read)) +- goto out; +- if (pos < 0) +- goto out; +- ret = read(file, buf, count, &pos); +- if (ret > 0) +- dnotify_parent(file->f_dentry, DN_ACCESS); +-out: +- fput(file); +-bad_file: +- return ret; ++ return sys_pread(fd, buf, count, merge_64(a4, a5)); + } + + asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, + size_t count, u32 unused, u64 a4, u64 a5) + { +- ssize_t ret; +- struct file * file; +- ssize_t (*write)(struct file *, const char *, size_t, loff_t *); +- loff_t pos; ++ return sys_pwrite(fd, buf, count, merge_64(a4, a5)); ++} + +- ret = -EBADF; +- file = fget(fd); +- if (!file) +- goto bad_file; +- if (!(file->f_mode & FMODE_WRITE)) +- goto out; +- pos = merge_64(a4, a5); +- ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode, +- file, pos, count); +- if (ret) +- goto out; +- ret = -EINVAL; +- if (!file->f_op || !(write = file->f_op->write)) +- goto out; +- if (pos < 0) +- goto out; + +- ret = write(file, buf, count, &pos); +- if (ret > 0) +- dnotify_parent(file->f_dentry, DN_MODIFY); +-out: +- fput(file); +-bad_file: +- return ret; +-} + /* + * Ooo, nasty. We need here to frob 32-bit unsigned longs to + * 64-bit unsigned longs. +@@ -2792,7 +2737,8 @@ + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) ++static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, ++ unsigned long orig_cmsg_uptr, __kernel_size_t orig_cmsg_len) + { + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; +@@ -2823,6 +2769,9 @@ + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; ++ if ((clen64 < CMSG_ALIGN(sizeof(*ucmsg))) || ++ (clen64 > (orig_cmsg_len + wp - workbuf))) ++ break; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + +@@ -2908,6 +2857,7 @@ + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; ++ __kernel_size_t cmsg_len; + int err, total_len, len = 0; + + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) +@@ -2923,6 +2873,7 @@ + total_len = err; + + cmsg_ptr = (unsigned long) kern_msg.msg_control; ++ cmsg_len = kern_msg.msg_controllen; + kern_msg.msg_flags = 0; + + sock = sockfd_lookup(fd, &err); +@@ -2948,7 +2899,8 @@ + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) +- cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); ++ cmsg32_recvmsg_fixup(&kern_msg, ++ cmsg_ptr, cmsg_len); + + /* Wheee... */ + if(sock->passcred) diff -Nur linux-2.4.29/arch/mips64/kernel/scall_64.S linux-mips/arch/mips64/kernel/scall_64.S --- linux-2.4.29/arch/mips64/kernel/scall_64.S 2005-01-19 15:09:32.000000000 +0100 -+++ linux-mips/arch/mips64/kernel/scall_64.S 2005-02-12 04:05:40.000000000 +0100 ++++ linux-mips/arch/mips64/kernel/scall_64.S 2005-03-26 11:47:18.698582876 +0100 @@ -102,15 +102,14 @@ trace_a_syscall: @@ -9358,7 +11200,7 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/scall_64.S linux-mips/arch/mips64/kern sltu t0, t0, v0 diff -Nur linux-2.4.29/arch/mips64/kernel/scall_n32.S linux-mips/arch/mips64/kernel/scall_n32.S --- linux-2.4.29/arch/mips64/kernel/scall_n32.S 2005-01-19 15:09:32.000000000 +0100 -+++ linux-mips/arch/mips64/kernel/scall_n32.S 2005-02-12 04:05:40.000000000 +0100 ++++ linux-mips/arch/mips64/kernel/scall_n32.S 2005-03-26 11:47:18.734576968 +0100 @@ -106,15 +106,14 @@ trace_a_syscall: @@ -9379,7 +11221,7 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/scall_n32.S linux-mips/arch/mips64/ker sltu t0, t0, v0 diff -Nur linux-2.4.29/arch/mips64/kernel/scall_o32.S linux-mips/arch/mips64/kernel/scall_o32.S --- linux-2.4.29/arch/mips64/kernel/scall_o32.S 2005-01-19 15:09:32.000000000 +0100 -+++ linux-mips/arch/mips64/kernel/scall_o32.S 2005-02-12 04:05:41.000000000 +0100 ++++ linux-mips/arch/mips64/kernel/scall_o32.S 2005-03-26 11:47:18.788568107 +0100 @@ -118,9 +118,8 @@ sd a6, PT_R10(sp) sd a7, PT_R11(sp) @@ -9400,6 +11242,15 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/scall_o32.S linux-mips/arch/mips64/ker li t0, -EMAXERRNO - 1 # error? sltu t0, t0, v0 +@@ -576,6 +575,8 @@ + sys_call_table: + syscalltable + ++ .purgem sys ++ + .macro sys function, nargs + .byte \nargs + .endm diff -Nur linux-2.4.29/arch/mips64/kernel/setup.c linux-mips/arch/mips64/kernel/setup.c --- linux-2.4.29/arch/mips64/kernel/setup.c 2005-01-19 15:09:32.000000000 +0100 +++ linux-mips/arch/mips64/kernel/setup.c 2004-11-22 14:38:26.000000000 +0100 @@ -9420,7 +11271,7 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/setup.c linux-mips/arch/mips64/kernel/ diff -Nur linux-2.4.29/arch/mips64/kernel/signal_n32.c linux-mips/arch/mips64/kernel/signal_n32.c --- linux-2.4.29/arch/mips64/kernel/signal_n32.c 2005-01-19 15:09:33.000000000 +0100 -+++ linux-mips/arch/mips64/kernel/signal_n32.c 2005-02-12 04:05:41.000000000 +0100 ++++ linux-mips/arch/mips64/kernel/signal_n32.c 2005-03-26 11:47:18.811564333 +0100 @@ -68,7 +68,7 @@ }; @@ -9490,39 +11341,6 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/traps.c linux-mips/arch/mips64/kernel/ - current->active_mm = &init_mm; + per_cpu_trap_init(); } -diff -Nur linux-2.4.29/arch/mips64/mm/c-r4k.c linux-mips/arch/mips64/mm/c-r4k.c ---- linux-2.4.29/arch/mips64/mm/c-r4k.c 2005-01-19 15:09:33.000000000 +0100 -+++ linux-mips/arch/mips64/mm/c-r4k.c 2005-02-12 04:05:41.000000000 +0100 -@@ -867,9 +867,16 @@ - * normally they'd suffer from aliases but magic in the hardware deals - * with that for us so we don't need to take care ourselves. - */ -- if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000) -- if (c->dcache.waysize > PAGE_SIZE) -- c->dcache.flags |= MIPS_CACHE_ALIASES; -+ switch (c->cputype) { -+ case CPU_R10000: -+ case CPU_R12000: -+ break; -+ case CPU_24K: -+ if (!(read_c0_config7() & (1 << 16))) -+ default: -+ if (c->dcache.waysize > PAGE_SIZE) -+ c->dcache.flags |= MIPS_CACHE_ALIASES; -+ } - - switch (c->cputype) { - case CPU_20KC: -@@ -1070,9 +1077,6 @@ - setup_scache(); - coherency_setup(); - -- if (c->dcache.sets * c->dcache.ways > PAGE_SIZE) -- c->dcache.flags |= MIPS_CACHE_ALIASES; -- - r4k_blast_dcache_page_setup(); - r4k_blast_dcache_page_indexed_setup(); - r4k_blast_dcache_setup(); diff -Nur linux-2.4.29/arch/mips64/mm/cerr-sb1.c linux-mips/arch/mips64/mm/cerr-sb1.c --- linux-2.4.29/arch/mips64/mm/cerr-sb1.c 2004-02-18 14:36:30.000000000 +0100 +++ linux-mips/arch/mips64/mm/cerr-sb1.c 2004-12-13 18:37:26.000000000 +0100 @@ -9570,6 +11388,98 @@ diff -Nur linux-2.4.29/arch/mips64/mm/cerr-sb1.c linux-mips/arch/mips64/mm/cerr- if (way == 0) { lru = (taghi >> 14) & 0xff; prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n", +diff -Nur linux-2.4.29/arch/mips64/mm/c-r4k.c linux-mips/arch/mips64/mm/c-r4k.c +--- linux-2.4.29/arch/mips64/mm/c-r4k.c 2005-01-19 15:09:33.000000000 +0100 ++++ linux-mips/arch/mips64/mm/c-r4k.c 2005-03-26 11:47:18.942542836 +0100 +@@ -867,9 +867,16 @@ + * normally they'd suffer from aliases but magic in the hardware deals + * with that for us so we don't need to take care ourselves. + */ +- if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000) +- if (c->dcache.waysize > PAGE_SIZE) +- c->dcache.flags |= MIPS_CACHE_ALIASES; ++ switch (c->cputype) { ++ case CPU_R10000: ++ case CPU_R12000: ++ break; ++ case CPU_24K: ++ if (!(read_c0_config7() & (1 << 16))) ++ default: ++ if (c->dcache.waysize > PAGE_SIZE) ++ c->dcache.flags |= MIPS_CACHE_ALIASES; ++ } + + switch (c->cputype) { + case CPU_20KC: +@@ -1070,9 +1077,6 @@ + setup_scache(); + coherency_setup(); + +- if (c->dcache.sets * c->dcache.ways > PAGE_SIZE) +- c->dcache.flags |= MIPS_CACHE_ALIASES; +- + r4k_blast_dcache_page_setup(); + r4k_blast_dcache_page_indexed_setup(); + r4k_blast_dcache_setup(); +diff -Nur linux-2.4.29/arch/mips64/mm/tlbex-r4k.S linux-mips/arch/mips64/mm/tlbex-r4k.S +--- linux-2.4.29/arch/mips64/mm/tlbex-r4k.S 2004-02-18 14:36:30.000000000 +0100 ++++ linux-mips/arch/mips64/mm/tlbex-r4k.S 2004-11-25 23:18:38.000000000 +0100 +@@ -151,11 +151,9 @@ + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 +- rm9000_tlb_hazard +- b 1f +- tlbwr +-1: nop +- rm9000_tlb_hazard ++ mtc0_tlbw_hazard ++ tlbwr ++1: tlbw_eret_hazard + eret + + 9: # handle the vmalloc range +@@ -163,11 +161,9 @@ + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 +- rm9000_tlb_hazard +- b 1f +- tlbwr +-1: nop +- rm9000_tlb_hazard ++ mtc0_tlbw_hazard ++ tlbwr ++1: tlbw_eret_hazard + eret + END(handle_vec1_r4k) + +@@ -195,10 +191,9 @@ + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 +- rm9000_tlb_hazard +- nop ++ mtc0_tlbw_hazard + tlbwr +- rm9000_tlb_hazard ++ tlbw_eret_hazard + eret + + 9: # handle the vmalloc range +@@ -206,10 +201,9 @@ + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 +- rm9000_tlb_hazard +- nop ++ mtc0_tlbw_hazard + tlbwr +- rm9000_tlb_hazard ++ tlbw_eret_hazard + eret + END(handle_vec1_r10k) + diff -Nur linux-2.4.29/arch/mips64/mm/tlb-r4k.c linux-mips/arch/mips64/mm/tlb-r4k.c --- linux-2.4.29/arch/mips64/mm/tlb-r4k.c 2005-01-19 15:09:33.000000000 +0100 +++ linux-mips/arch/mips64/mm/tlb-r4k.c 2004-11-25 23:18:38.000000000 +0100 @@ -9924,156 +11834,1598 @@ diff -Nur linux-2.4.29/arch/mips64/mm/tlb-r4k.c linux-mips/arch/mips64/mm/tlb-r4 probe_tlb(config); write_c0_pagemask(PM_DEFAULT_MASK); write_c0_wired(0); -diff -Nur linux-2.4.29/arch/mips64/mm/tlbex-r4k.S linux-mips/arch/mips64/mm/tlbex-r4k.S ---- linux-2.4.29/arch/mips64/mm/tlbex-r4k.S 2004-02-18 14:36:30.000000000 +0100 -+++ linux-mips/arch/mips64/mm/tlbex-r4k.S 2004-11-25 23:18:38.000000000 +0100 -@@ -151,11 +151,9 @@ - ld k0, 0(k1) # get even pte - ld k1, 8(k1) # get odd pte - PTE_RELOAD k0 k1 -- rm9000_tlb_hazard -- b 1f -- tlbwr --1: nop -- rm9000_tlb_hazard -+ mtc0_tlbw_hazard -+ tlbwr -+1: tlbw_eret_hazard - eret +diff -Nur linux-2.4.29/arch/parisc/kernel/sys_parisc32.c linux-mips/arch/parisc/kernel/sys_parisc32.c +--- linux-2.4.29/arch/parisc/kernel/sys_parisc32.c 2005-01-19 15:09:35.000000000 +0100 ++++ linux-mips/arch/parisc/kernel/sys_parisc32.c 2005-03-26 11:47:18.967538734 +0100 +@@ -1671,11 +1671,9 @@ + i--; + } - 9: # handle the vmalloc range -@@ -163,11 +161,9 @@ - ld k0, 0(k1) # get even pte - ld k1, 8(k1) # get odd pte - PTE_RELOAD k0 k1 -- rm9000_tlb_hazard -- b 1f -- tlbwr --1: nop -- rm9000_tlb_hazard -+ mtc0_tlbw_hazard -+ tlbwr -+1: tlbw_eret_hazard - eret - END(handle_vec1_r4k) +- inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ +- retval = locks_verify_area((type == VERIFY_WRITE +- ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), +- inode, file, file->f_pos, tot_len); ++ retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE), ++ file, &file->f_pos, tot_len); + if (retval) { + if (iov != iovstack) + kfree(iov); +@@ -2108,7 +2106,8 @@ + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) ++static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, ++ unsigned long orig_cmsg_uptr, __kernel_size_t orig_cmsg_len) + { + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; +@@ -2139,6 +2138,9 @@ + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; ++ if ((clen64 < CMSG_ALIGN(sizeof(*ucmsg))) || ++ (clen64 > (orig_cmsg_len + wp - workbuf))) ++ break; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + +@@ -2224,6 +2226,7 @@ + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; ++ __kernel_size_t cmsg_len; + int err, total_len, len = 0; + + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) +@@ -2239,6 +2242,7 @@ + total_len = err; + + cmsg_ptr = (unsigned long) kern_msg.msg_control; ++ cmsg_len = kern_msg.msg_controllen; + kern_msg.msg_flags = 0; + + sock = sockfd_lookup(fd, &err); +@@ -2264,7 +2268,8 @@ + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) +- cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); ++ cmsg32_recvmsg_fixup(&kern_msg, ++ cmsg_ptr, cmsg_len); + + /* Wheee... */ + if(sock->passcred) +diff -Nur linux-2.4.29/arch/ppc/kernel/cputable.c linux-mips/arch/ppc/kernel/cputable.c +--- linux-2.4.29/arch/ppc/kernel/cputable.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/arch/ppc/kernel/cputable.c 2005-03-26 11:47:18.990534959 +0100 +@@ -480,8 +480,8 @@ + 32, 32, + 0, /*__setup_cpu_440 */ + }, +- { /* 440GX Rev. B1 (2.1) */ +- 0xf0000fff, 0x50000852, "440GX Rev. B1 (2.1)", ++ { /* 440GX Rev. C */ ++ 0xf0000fff, 0x50000892, "440GX Rev. C", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 32, 32, +diff -Nur linux-2.4.29/arch/ppc/kernel/head_8xx.S linux-mips/arch/ppc/kernel/head_8xx.S +--- linux-2.4.29/arch/ppc/kernel/head_8xx.S 2004-02-18 14:36:30.000000000 +0100 ++++ linux-mips/arch/ppc/kernel/head_8xx.S 2005-03-26 11:47:18.992534631 +0100 +@@ -338,13 +338,13 @@ + 3: + lwz r21, 0(r20) /* Get the level 1 entry */ + rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */ +- beq 2f /* If zero, don't try to find a pte */ + + /* We have a pte table, so load the MI_TWC with the attributes + * for this "segment." + */ + tophys(r21,r21) + ori r21,r21,1 /* Set valid bit */ ++ beq- 2f /* If zero, don't try to find a pte */ + #ifdef CONFIG_8xx_CPU6 + li r3, 0x2b80 + stw r3, 12(r0) +@@ -369,7 +369,7 @@ + * set. All other Linux PTE bits control the behavior + * of the MMU. + */ +- li r21, 0x00f0 ++2: li r21, 0x00f0 + rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */ -@@ -195,10 +191,9 @@ - ld k0, 0(k1) # get even pte - ld k1, 8(k1) # get odd pte - PTE_RELOAD k0 k1 -- rm9000_tlb_hazard -- nop -+ mtc0_tlbw_hazard - tlbwr -- rm9000_tlb_hazard -+ tlbw_eret_hazard - eret + #ifdef CONFIG_8xx_CPU6 +@@ -388,15 +388,6 @@ + #endif + rfi + +-2: mfspr r20, M_TW /* Restore registers */ +- lwz r21, 0(r0) +- mtcr r21 +- lwz r21, 4(r0) +-#ifdef CONFIG_8xx_CPU6 +- lwz r3, 8(r0) +-#endif +- b InstructionAccess +- + . = 0x1200 + DataStoreTLBMiss: + #ifdef CONFIG_8xx_CPU6 +@@ -422,12 +413,12 @@ + 3: + lwz r21, 0(r20) /* Get the level 1 entry */ + rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */ +- beq 2f /* If zero, don't try to find a pte */ + + /* We have a pte table, so load fetch the pte from the table. + */ + tophys(r21, r21) + ori r21, r21, 1 /* Set valid bit in physical L2 page */ ++ beq- 2f /* If zero, don't try to find a pte */ + #ifdef CONFIG_8xx_CPU6 + li r3, 0x3b80 + stw r3, 12(r0) +@@ -461,7 +452,7 @@ + * set. All other Linux PTE bits control the behavior + * of the MMU. + */ +- li r21, 0x00f0 ++2: li r21, 0x00f0 + rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */ - 9: # handle the vmalloc range -@@ -206,10 +201,9 @@ - ld k0, 0(k1) # get even pte - ld k1, 8(k1) # get odd pte - PTE_RELOAD k0 k1 -- rm9000_tlb_hazard + #ifdef CONFIG_8xx_CPU6 +@@ -480,24 +471,6 @@ + #endif + rfi + +-2: +- /* Copy 20 msb from MD_EPN to DAR since the dcxx instructions fail +- * to update DAR when they cause a DTLB miss. +- */ +- mfspr r21, MD_EPN +- mfspr r20, DAR +- rlwimi r20, r21, 0, 0, 19 +- mtspr DAR, r20 +- +- mfspr r20, M_TW /* Restore registers */ +- lwz r21, 0(r0) +- mtcr r21 +- lwz r21, 4(r0) +-#ifdef CONFIG_8xx_CPU6 +- lwz r3, 8(r0) +-#endif +- b DataAccess +- + /* This is an instruction TLB error on the MPC8xx. This could be due + * to many reasons, such as executing guarded memory or illegal instruction + * addresses. There is nothing to do but handle a big time error fault. +diff -Nur linux-2.4.29/arch/ppc64/kernel/sys_ppc32.c linux-mips/arch/ppc64/kernel/sys_ppc32.c +--- linux-2.4.29/arch/ppc64/kernel/sys_ppc32.c 2005-01-19 15:09:37.000000000 +0100 ++++ linux-mips/arch/ppc64/kernel/sys_ppc32.c 2005-03-26 11:47:19.016530693 +0100 +@@ -183,11 +183,9 @@ + i--; + } + +- inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ +- retval = locks_verify_area((type == VERIFY_WRITE +- ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), +- inode, file, file->f_pos, tot_len); ++ retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE), ++ file, &file->f_pos, tot_len); + if (retval) { + if (iov != iovstack) + kfree(iov); +@@ -3666,7 +3664,8 @@ + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) ++static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, ++ unsigned long orig_cmsg_uptr, __kernel_size_t orig_cmsg_len) + { + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; +@@ -3697,6 +3696,9 @@ + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; ++ if ((clen64 < CMSG_ALIGN(sizeof(*ucmsg))) || ++ (clen64 > (orig_cmsg_len + wp - workbuf))) ++ break; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + +@@ -3753,6 +3755,7 @@ + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; ++ __kernel_size_t cmsg_len; + int err, total_len, len = 0; + + PPCDBG(PPCDBG_SYS32, "sys32_recvmsg - entered - fd=%x, user_msg@=%p, user_flags=%x \n", fd, user_msg, user_flags); +@@ -3770,6 +3773,7 @@ + total_len = err; + + cmsg_ptr = (unsigned long) kern_msg.msg_control; ++ cmsg_len = kern_msg.msg_controllen; + kern_msg.msg_flags = 0; + + sock = sockfd_lookup(fd, &err); +@@ -3795,7 +3799,8 @@ + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) +- cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); ++ cmsg32_recvmsg_fixup(&kern_msg, ++ cmsg_ptr, cmsg_len); + + /* Wheee... */ + if(sock->passcred) +diff -Nur linux-2.4.29/arch/s390x/kernel/linux32.c linux-mips/arch/s390x/kernel/linux32.c +--- linux-2.4.29/arch/s390x/kernel/linux32.c 2005-01-19 15:09:38.000000000 +0100 ++++ linux-mips/arch/s390x/kernel/linux32.c 2005-03-26 11:47:19.529446512 +0100 +@@ -1108,7 +1108,6 @@ + unsigned long tot_len; + struct iovec iovstack[UIO_FASTIOV]; + struct iovec *iov=iovstack, *ivp; +- struct inode *inode; + long retval, i; + io_fn_t fn; + iov_fn_t fnv; +@@ -1145,11 +1144,9 @@ + i--; + } + +- inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ +- retval = locks_verify_area((type == VERIFY_WRITE +- ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), +- inode, file, file->f_pos, tot_len); ++ retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE), ++ file, &file->f_pos, tot_len); + if (retval) + goto out; + +@@ -2600,7 +2597,8 @@ + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) ++static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, ++ unsigned long orig_cmsg_uptr, __kernel_size_t orig_cmsg_len) + { + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; +@@ -2631,6 +2629,9 @@ + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; ++ if ((clen64 < CMSG_ALIGN(sizeof(*ucmsg))) || ++ (clen64 > (orig_cmsg_len + wp - workbuf))) ++ break; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + +@@ -2890,7 +2891,8 @@ + + static __inline__ void + scm_recv32(struct socket *sock, struct msghdr *msg, +- struct scm_cookie *scm, int flags, unsigned long cmsg_ptr) ++ struct scm_cookie *scm, int flags, unsigned long cmsg_ptr, ++ __kernel_size_t cmsg_len) + { + if(!msg->msg_control) + { +@@ -2905,7 +2907,7 @@ + * to fix it up before we tack on more stuff. + */ + if((unsigned long) msg->msg_control != cmsg_ptr) +- cmsg32_recvmsg_fixup(msg, cmsg_ptr); ++ cmsg32_recvmsg_fixup(msg, cmsg_ptr, cmsg_len); + /* Wheee... */ + if(sock->passcred) + put_cmsg32(msg, +@@ -2919,14 +2921,14 @@ + + static int + sock_recvmsg32(struct socket *sock, struct msghdr *msg, int size, int flags, +- unsigned long cmsg_ptr) ++ unsigned long cmsg_ptr, __kernel_size_t cmsg_len) + { + struct scm_cookie scm; + + memset(&scm, 0, sizeof(scm)); + size = sock->ops->recvmsg(sock, msg, size, flags, &scm); + if (size >= 0) +- scm_recv32(sock, msg, &scm, flags, cmsg_ptr); ++ scm_recv32(sock, msg, &scm, flags, cmsg_ptr, cmsg_len); + + return size; + } +@@ -2943,6 +2945,7 @@ + struct iovec *iov=iovstack; + struct msghdr msg_sys; + unsigned long cmsg_ptr; ++ __kernel_size_t cmsg_len; + int err, iov_size, total_len, len; + + /* kernel mode address */ +@@ -2986,11 +2989,12 @@ + total_len=err; + + cmsg_ptr = (unsigned long)msg_sys.msg_control; ++ cmsg_len = msg_sys.msg_controllen; + msg_sys.msg_flags = 0; + + if (sock->file->f_flags & O_NONBLOCK) + flags |= MSG_DONTWAIT; +- err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr); ++ err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr, cmsg_len); + if (err < 0) + goto out_freeiov; + len = err; +diff -Nur linux-2.4.29/arch/sparc/kernel/muldiv.c linux-mips/arch/sparc/kernel/muldiv.c +--- linux-2.4.29/arch/sparc/kernel/muldiv.c 1998-01-13 00:15:43.000000000 +0100 ++++ linux-mips/arch/sparc/kernel/muldiv.c 2005-03-26 11:47:19.631429774 +0100 +@@ -4,6 +4,9 @@ + * + * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) ++ * ++ * 2004-12-25 Krzysztof Helt (krzysztof.h1@wp.pl) ++ * - fixed registers constrains in inline assembly declarations + */ + + #include <linux/kernel.h> +@@ -125,7 +128,7 @@ + "mov %%o0, %0\n\t" + "mov %%o1, %1\n\t" + : "=r" (rs1), "=r" (rs2) +- : ++ : "0" (rs1), "1" (rs2) + : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc"); + #ifdef DEBUG_MULDIV + printk ("0x%x%08x\n", rs2, rs1); +@@ -145,7 +148,7 @@ + "mov %%o0, %0\n\t" + "mov %%o1, %1\n\t" + : "=r" (rs1), "=r" (rs2) +- : ++ : "0" (rs1), "1" (rs2) + : "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc"); + #ifdef DEBUG_MULDIV + printk ("0x%x%08x\n", rs2, rs1); +@@ -174,7 +177,7 @@ + "mov %%o1, %0\n\t" + "mov %%o0, %1\n\t" + : "=r" (rs1), "=r" (rs2) +- : "r" (regs->y) ++ : "r" (regs->y), "0" (rs1), "1" (rs2) + : "o0", "o1", "o2", "o3", "o4", "o5", "o7", + "g1", "g2", "g3", "cc"); + #ifdef DEBUG_MULDIV +@@ -203,7 +206,7 @@ + "mov %%o1, %0\n\t" + "mov %%o0, %1\n\t" + : "=r" (rs1), "=r" (rs2) +- : "r" (regs->y) ++ : "r" (regs->y), "0" (rs1), "1" (rs2) + : "o0", "o1", "o2", "o3", "o4", "o5", "o7", + "g1", "g2", "g3", "cc"); + #ifdef DEBUG_MULDIV +diff -Nur linux-2.4.29/arch/sparc/kernel/process.c linux-mips/arch/sparc/kernel/process.c +--- linux-2.4.29/arch/sparc/kernel/process.c 2004-08-08 01:26:04.000000000 +0200 ++++ linux-mips/arch/sparc/kernel/process.c 2005-03-26 11:47:19.632429610 +0100 +@@ -512,6 +512,11 @@ + } + } + ++#ifdef CONFIG_SMP ++ /* FPU must be disabled on SMP. */ ++ childregs->psr &= ~PSR_EF; ++#endif ++ + /* Set the return value for the child. */ + childregs->u_regs[UREG_I0] = current->pid; + childregs->u_regs[UREG_I1] = 1; +diff -Nur linux-2.4.29/arch/sparc64/kernel/ioctl32.c linux-mips/arch/sparc64/kernel/ioctl32.c +--- linux-2.4.29/arch/sparc64/kernel/ioctl32.c 2005-01-19 15:09:39.000000000 +0100 ++++ linux-mips/arch/sparc64/kernel/ioctl32.c 2005-03-26 11:47:19.641428133 +0100 +@@ -562,6 +562,8 @@ + + if (!(current->thread.flags & SPARC_FLAG_32BIT)) + usp += STACK_BIAS; ++ else ++ usp &= 0xffffffffUL; + + return (void *) (usp - len); + } +@@ -696,6 +698,7 @@ + set_fs (old_fs); + if (!err) { + switch (cmd) { ++ case TUNSETIFF: + case SIOCGIFFLAGS: + case SIOCGIFMETRIC: + case SIOCGIFMTU: +diff -Nur linux-2.4.29/arch/sparc64/kernel/pci_schizo.c linux-mips/arch/sparc64/kernel/pci_schizo.c +--- linux-2.4.29/arch/sparc64/kernel/pci_schizo.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/arch/sparc64/kernel/pci_schizo.c 2005-03-26 11:47:19.646427312 +0100 +@@ -388,9 +388,9 @@ + return ret; + } + +-static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm, +- struct pci_dev *pdev, +- unsigned int ino) ++static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, ++ struct pci_dev *pdev, ++ unsigned int ino) + { + struct ino_bucket *bucket; + unsigned long imap, iclr; +@@ -444,19 +444,57 @@ + static unsigned long stc_tag_buf[16]; + static unsigned long stc_line_buf[16]; + +-/* These offsets look weird because I keep in pbm->controller_regs +- * the second PROM register property minus 0x10000 which is the +- * base of the Safari and UPA64S registers of SCHIZO. +- */ +-#define SCHIZO_PBM_A_REGS_OFF (0x600000UL - 0x400000UL) +-#define SCHIZO_PBM_B_REGS_OFF (0x700000UL - 0x400000UL) ++#define SCHIZO_UE_INO 0x30 /* Uncorrectable ECC error */ ++#define SCHIZO_CE_INO 0x31 /* Correctable ECC error */ ++#define SCHIZO_PCIERR_A_INO 0x32 /* PBM A PCI bus error */ ++#define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */ ++#define SCHIZO_SERR_INO 0x34 /* Safari interface error */ ++ ++struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) ++{ ++ ino &= IMAP_INO; ++ if (p->pbm_A.ino_bitmap & (1UL << ino)) ++ return &p->pbm_A; ++ if (p->pbm_B.ino_bitmap & (1UL << ino)) ++ return &p->pbm_B; ++ ++ printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps " ++ "PBM_A[%016lx] PBM_B[%016lx]", ++ p->index, ino, ++ p->pbm_A.ino_bitmap, ++ p->pbm_B.ino_bitmap); ++ printk("PCI%d: Using PBM_A, report this problem immediately.\n", ++ p->index); ++ ++ return &p->pbm_A; ++} + +-static void schizo_clear_other_err_intr(int irq) ++static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) + { +- struct ino_bucket *bucket = __bucket(irq); +- unsigned long iclr = bucket->iclr; ++ struct pci_pbm_info *pbm; ++ struct ino_bucket *bucket; ++ unsigned long iclr; ++ ++ /* Do not clear the interrupt for the other PCI bus. ++ * ++ * This "ACK both PBM IRQs" only needs to be performed ++ * for chip-wide error interrupts. ++ */ ++ if ((irq & IMAP_INO) == SCHIZO_PCIERR_A_INO || ++ (irq & IMAP_INO) == SCHIZO_PCIERR_B_INO) ++ return; ++ ++ pbm = pbm_for_ino(p, irq); ++ if (pbm == &p->pbm_A) ++ pbm = &p->pbm_B; ++ else ++ pbm = &p->pbm_A; ++ ++ irq = schizo_irq_build(pbm, NULL, ++ (pbm->portid << 6) | (irq & IMAP_INO)); ++ bucket = __bucket(irq); ++ iclr = bucket->iclr; + +- iclr += (SCHIZO_PBM_B_REGS_OFF - SCHIZO_PBM_A_REGS_OFF); + upa_writel(ICLR_IDLE, iclr); + } + +@@ -790,7 +828,7 @@ + /* Interrogate IOMMU for error status. */ + schizo_check_iommu_error(p, UE_ERR); + +- schizo_clear_other_err_intr(irq); ++ schizo_clear_other_err_intr(p, irq); + } + + #define SCHIZO_CE_AFSR 0x10040UL +@@ -879,7 +917,7 @@ + printk("(none)"); + printk("]\n"); + +- schizo_clear_other_err_intr(irq); ++ schizo_clear_other_err_intr(p, irq); + } + + #define SCHIZO_PCI_AFSR 0x2010UL +@@ -914,9 +952,9 @@ + #define SCHIZO_PCICTRL_SBH_ERR (1UL << 35UL) /* Safari */ + #define SCHIZO_PCICTRL_SERR (1UL << 34UL) /* Safari/Tomatillo */ + #define SCHIZO_PCICTRL_PCISPD (1UL << 33UL) /* Safari */ +-#define SCHIZO_PCICTRL_MRM_PREF (1UL << 28UL) /* Tomatillo */ +-#define SCHIZO_PCICTRL_RDO_PREF (1UL << 27UL) /* Tomatillo */ +-#define SCHIZO_PCICTRL_RDL_PREF (1UL << 26UL) /* Tomatillo */ ++#define SCHIZO_PCICTRL_MRM_PREF (1UL << 30UL) /* Tomatillo */ ++#define SCHIZO_PCICTRL_RDO_PREF (1UL << 29UL) /* Tomatillo */ ++#define SCHIZO_PCICTRL_RDL_PREF (1UL << 28UL) /* Tomatillo */ + #define SCHIZO_PCICTRL_PTO (3UL << 24UL) /* Safari/Tomatillo */ + #define SCHIZO_PCICTRL_PTO_SHIFT 24UL + #define SCHIZO_PCICTRL_TRWSW (7UL << 21UL) /* Tomatillo */ +@@ -1094,7 +1132,7 @@ + if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR)) + pci_scan_for_parity_error(p, pbm, pbm->pci_bus); + +- schizo_clear_other_err_intr(irq); ++ schizo_clear_other_err_intr(p, irq); + } + + #define SCHIZO_SAFARI_ERRLOG 0x10018UL +@@ -1149,7 +1187,7 @@ + printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", + p->index, errlog); + +- schizo_clear_other_err_intr(irq); ++ schizo_clear_other_err_intr(p, irq); + return; + } + +@@ -1157,7 +1195,7 @@ + p->index); + schizo_check_iommu_error(p, SAFARI_ERR); + +- schizo_clear_other_err_intr(irq); ++ schizo_clear_other_err_intr(p, irq); + } + + /* Nearly identical to PSYCHO equivalents... */ +@@ -1171,26 +1209,6 @@ + #define SCHIZO_SAFARI_IRQCTRL 0x10010UL + #define SCHIZO_SAFIRQCTRL_EN 0x8000000000000000UL + +-#define SCHIZO_UE_INO 0x30 /* Uncorrectable ECC error */ +-#define SCHIZO_CE_INO 0x31 /* Correctable ECC error */ +-#define SCHIZO_PCIERR_A_INO 0x32 /* PBM A PCI bus error */ +-#define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */ +-#define SCHIZO_SERR_INO 0x34 /* Safari interface error */ +- +-struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) +-{ +- ino &= IMAP_INO; +- if (p->pbm_A.ino_bitmap & (1UL << ino)) +- return &p->pbm_A; +- if (p->pbm_B.ino_bitmap & (1UL << ino)) +- return &p->pbm_B; +- prom_printf("TOMATILLO%d: No entry in ino bitmap for %d\n", +- p->index, ino); +- prom_halt(); +- /* NOTREACHED */ +- return NULL; +-} +- + /* How the Tomatillo IRQs are routed around is pure guesswork here. + * + * All the Tomatillo devices I see in prtconf dumps seem to have only +@@ -1964,7 +1982,7 @@ + + tmp &= ~SCHIZO_PCICTRL_PTO; + if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO && +- pbm->chip_version == 0x2) ++ pbm->chip_version >= 0x2) + tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; + else + tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT; +@@ -1972,8 +1990,16 @@ + if (!prom_getbool(pbm->prom_node, "no-bus-parking")) + tmp |= SCHIZO_PCICTRL_PARK; + ++ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO && ++ pbm->chip_version <= 0x1) ++ tmp |= (1UL << 61); ++ else ++ tmp &= ~(1UL << 61); ++ + if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) +- tmp |= SCHIZO_PCICTRL_MRM_PREF; ++ tmp |= (SCHIZO_PCICTRL_MRM_PREF | ++ SCHIZO_PCICTRL_RDO_PREF | ++ SCHIZO_PCICTRL_RDL_PREF); + + schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + +diff -Nur linux-2.4.29/arch/sparc64/kernel/smp.c linux-mips/arch/sparc64/kernel/smp.c +--- linux-2.4.29/arch/sparc64/kernel/smp.c 2005-01-19 15:09:39.000000000 +0100 ++++ linux-mips/arch/sparc64/kernel/smp.c 2005-03-26 11:47:19.647427148 +0100 +@@ -1034,7 +1034,7 @@ + void smp_capture(void) + { + if (smp_processors_ready) { +- int result = __atomic_add(1, &smp_capture_depth); ++ int result = atomic_add_ret(1, &smp_capture_depth); + + membar("#StoreStore | #LoadStore"); + if (result == 1) { +diff -Nur linux-2.4.29/arch/sparc64/kernel/sparc64_ksyms.c linux-mips/arch/sparc64/kernel/sparc64_ksyms.c +--- linux-2.4.29/arch/sparc64/kernel/sparc64_ksyms.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/arch/sparc64/kernel/sparc64_ksyms.c 2005-03-26 11:47:19.648426984 +0100 +@@ -173,18 +173,21 @@ + EXPORT_SYMBOL(__up); + + /* Atomic counter implementation. */ +-EXPORT_SYMBOL(__atomic_add); +-EXPORT_SYMBOL(__atomic_sub); ++EXPORT_SYMBOL(atomic_add); ++EXPORT_SYMBOL(atomic_add_ret); ++EXPORT_SYMBOL(atomic_sub); ++EXPORT_SYMBOL(atomic_sub_ret); + #ifdef CONFIG_SMP + EXPORT_SYMBOL(atomic_dec_and_lock); + #endif + + /* Atomic bit operations. */ +-EXPORT_SYMBOL(___test_and_set_bit); +-EXPORT_SYMBOL(___test_and_clear_bit); +-EXPORT_SYMBOL(___test_and_change_bit); +-EXPORT_SYMBOL(___test_and_set_le_bit); +-EXPORT_SYMBOL(___test_and_clear_le_bit); ++EXPORT_SYMBOL(test_and_set_bit); ++EXPORT_SYMBOL(test_and_clear_bit); ++EXPORT_SYMBOL(test_and_change_bit); ++EXPORT_SYMBOL(set_bit); ++EXPORT_SYMBOL(clear_bit); ++EXPORT_SYMBOL(change_bit); + + EXPORT_SYMBOL(ivector_table); + EXPORT_SYMBOL(enable_irq); +diff -Nur linux-2.4.29/arch/sparc64/kernel/sys_sparc32.c linux-mips/arch/sparc64/kernel/sys_sparc32.c +--- linux-2.4.29/arch/sparc64/kernel/sys_sparc32.c 2005-01-19 15:09:39.000000000 +0100 ++++ linux-mips/arch/sparc64/kernel/sys_sparc32.c 2005-03-26 11:47:19.669423538 +0100 +@@ -505,25 +505,32 @@ + return err; + } + +-static int do_sys32_msgsnd (int first, int second, int third, void *uptr) ++static int do_sys32_msgsnd(int first, int second, int third, void *uptr) + { +- struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER); +- struct msgbuf32 *up = (struct msgbuf32 *)uptr; ++ struct msgbuf *p; ++ struct msgbuf32 *up; + mm_segment_t old_fs; + int err; + ++ if (second < 0) ++ return -EINVAL; ++ ++ p = kmalloc(second + sizeof (struct msgbuf), GFP_USER); + if (!p) + return -ENOMEM; ++ ++ up = (struct msgbuf32 *)uptr; + err = -EFAULT; +- if (get_user (p->mtype, &up->mtype) || +- __copy_from_user (p->mtext, &up->mtext, second)) ++ if (get_user(p->mtype, &up->mtype) || ++ __copy_from_user(p->mtext, up->mtext, second)) + goto out; +- old_fs = get_fs (); +- set_fs (KERNEL_DS); +- err = sys_msgsnd (first, p, second, third); +- set_fs (old_fs); ++ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ err = sys_msgsnd(first, p, second, third); ++ set_fs(old_fs); + out: +- kfree (p); ++ kfree(p); + return err; + } + +@@ -535,6 +542,9 @@ + mm_segment_t old_fs; + int err; + ++ if (second < 0) ++ return -EINVAL; ++ + if (!version) { + struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; + struct ipc_kludge ipck; +@@ -560,7 +570,7 @@ + goto free_then_out; + up = (struct msgbuf32 *)uptr; + if (put_user (p->mtype, &up->mtype) || +- __copy_to_user (&up->mtext, p->mtext, err)) ++ __copy_to_user (up->mtext, p->mtext, err)) + err = -EFAULT; + free_then_out: + kfree (p); +@@ -647,18 +657,18 @@ + return err; + } + +-static int do_sys32_shmat (int first, int second, int third, int version, void *uptr) ++static int do_sys32_shmat(int first, int second, u32 third, int version, void *uptr) + { + unsigned long raddr; +- u32 *uaddr = (u32 *)A((u32)third); ++ u32 *uaddr = (u32 *)A(third); + int err = -EINVAL; + + if (version == 1) + goto out; +- err = sys_shmat (first, uptr, second, &raddr); ++ err = sys_shmat(first, uptr, second, &raddr); + if (err) + goto out; +- err = put_user (raddr, uaddr); ++ err = put_user(raddr, uaddr); + out: + return err; + } +@@ -770,6 +780,8 @@ + + if (!(current->thread.flags & SPARC_FLAG_32BIT)) + usp += STACK_BIAS; ++ else ++ usp &= 0xffffffffUL; + + return (void *) (usp - len); + } +@@ -795,9 +807,11 @@ + return sys_semtimedop(semid, tsems, nsems, t64); + } + +-asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) ++asmlinkage int sys32_ipc (u32 call, u32 first, u32 second, u32 third, s32 __ptr, s32 __fifth) + { + int version, err; ++ u32 ptr = (u32) __ptr; ++ u32 fifth = (u32) __fifth; + + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; +@@ -806,15 +820,23 @@ + switch (call) { + case SEMOP: + /* struct sembuf is the same on 32 and 64bit :)) */ +- err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL); ++ err = sys_semtimedop((int)first, ++ (struct sembuf *)A(ptr), ++ second, NULL); + goto out; + case SEMTIMEDOP: +- err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct timespec32 *) AA(fifth)); ++ err = sys32_semtimedop((int)first, ++ (struct sembuf *)A(ptr), ++ second, ++ (const struct timespec32 *) ++ A(third)); + case SEMGET: +- err = sys_semget (first, second, third); ++ err = sys_semget((key_t)first, (int)second, ++ (int)third); + goto out; + case SEMCTL: +- err = do_sys32_semctl (first, second, third, (void *)AA(ptr)); ++ err = do_sys32_semctl((int)first, (int)second, ++ (int)third, (void *) A(ptr)); + goto out; + default: + err = -ENOSYS; +@@ -823,17 +845,20 @@ + if (call <= MSGCTL) + switch (call) { + case MSGSND: +- err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr)); ++ err = do_sys32_msgsnd((int)first, (int)second, ++ (int)third, (void *)A(ptr)); + goto out; + case MSGRCV: +- err = do_sys32_msgrcv (first, second, fifth, third, +- version, (void *)AA(ptr)); ++ err = do_sys32_msgrcv((int)first, (int)second, ++ (int)fifth, (int)third, ++ version, (void *)A(ptr)); + goto out; + case MSGGET: +- err = sys_msgget ((key_t) first, second); ++ err = sys_msgget((key_t)first, (int)second); + goto out; + case MSGCTL: +- err = do_sys32_msgctl (first, second, (void *)AA(ptr)); ++ err = do_sys32_msgctl((int)first, (int)second, ++ (void *)A(ptr)); + goto out; + default: + err = -ENOSYS; +@@ -842,17 +867,18 @@ + if (call <= SHMCTL) + switch (call) { + case SHMAT: +- err = do_sys32_shmat (first, second, third, +- version, (void *)AA(ptr)); ++ err = do_sys32_shmat((int)first, (int)second, third, ++ version, (void *)A(ptr)); + goto out; + case SHMDT: +- err = sys_shmdt ((char *)AA(ptr)); ++ err = sys_shmdt((char *)A(ptr)); + goto out; + case SHMGET: +- err = sys_shmget (first, second, third); ++ err = sys_shmget((key_t)first, second, (int)third); + goto out; + case SHMCTL: +- err = do_sys32_shmctl (first, second, (void *)AA(ptr)); ++ err = do_sys32_shmctl((int)first, (int)second, ++ (void *)A(ptr)); + goto out; + default: + err = -ENOSYS; +@@ -1093,7 +1119,6 @@ + __kernel_ssize_t32 tot_len; + struct iovec iovstack[UIO_FASTIOV]; + struct iovec *iov=iovstack, *ivp; +- struct inode *inode; + long retval, i; + io_fn_t fn; + iov_fn_t fnv; +@@ -1140,11 +1165,9 @@ + i--; + } + +- inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ +- retval = locks_verify_area((type == VERIFY_WRITE +- ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), +- inode, file, file->f_pos, tot_len); ++ retval = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE), ++ file, &file->f_pos, tot_len); + if (retval) + goto out; + +@@ -2160,9 +2183,6 @@ + timeout = (timespec_to_jiffies(&ts) + + (ts.tv_sec || ts.tv_nsec)); + +- current->state = TASK_INTERRUPTIBLE; +- timeout = schedule_timeout(timeout); +- + if (timeout) { + /* None ready -- temporarily unblock those we're + * interested while we are sleeping in so that we'll +@@ -2648,7 +2668,8 @@ + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) ++static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, ++ unsigned long orig_cmsg_uptr, __kernel_size_t orig_cmsg_len) + { + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; +@@ -2679,6 +2700,9 @@ + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; ++ if ((clen64 < CMSG_ALIGN(sizeof(*ucmsg))) || ++ (clen64 > (orig_cmsg_len + wp - workbuf))) ++ break; + if (kcmsg32->cmsg_level == SOL_SOCKET && + kcmsg32->cmsg_type == SO_TIMESTAMP) { + struct timeval tv; +@@ -2782,6 +2806,7 @@ + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; ++ __kernel_size_t cmsg_len; + int err, total_len, len = 0; + + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) +@@ -2797,6 +2822,7 @@ + total_len = err; + + cmsg_ptr = (unsigned long) kern_msg.msg_control; ++ cmsg_len = kern_msg.msg_controllen; + kern_msg.msg_flags = 0; + + sock = sockfd_lookup(fd, &err); +@@ -2822,7 +2848,8 @@ + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) +- cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); ++ cmsg32_recvmsg_fixup(&kern_msg, ++ cmsg_ptr, cmsg_len); + + /* Wheee... */ + if(sock->passcred) +diff -Nur linux-2.4.29/arch/sparc64/kernel/time.c linux-mips/arch/sparc64/kernel/time.c +--- linux-2.4.29/arch/sparc64/kernel/time.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/arch/sparc64/kernel/time.c 2005-03-26 11:47:19.670423374 +0100 +@@ -770,6 +770,7 @@ + strcmp(model, "mk48t59") && + strcmp(model, "m5819") && + strcmp(model, "m5819p") && ++ strcmp(model, "m5823") && + strcmp(model, "ds1287")) { + if (cbus != NULL) { + prom_printf("clock_probe: Central bus lacks timer chip.\n"); +@@ -829,7 +830,8 @@ + + if (!strcmp(model, "ds1287") || + !strcmp(model, "m5819") || +- !strcmp(model, "m5819p")) { ++ !strcmp(model, "m5819p") || ++ !strcmp(model, "m5823")) { + ds1287_regs = edev->resource[0].start; + } else { + mstk48t59_regs = edev->resource[0].start; +@@ -850,7 +852,8 @@ + } + if (!strcmp(model, "ds1287") || + !strcmp(model, "m5819") || +- !strcmp(model, "m5819p")) { ++ !strcmp(model, "m5819p") || ++ !strcmp(model, "m5823")) { + ds1287_regs = isadev->resource.start; + } else { + mstk48t59_regs = isadev->resource.start; +diff -Nur linux-2.4.29/arch/sparc64/lib/atomic.S linux-mips/arch/sparc64/lib/atomic.S +--- linux-2.4.29/arch/sparc64/lib/atomic.S 2001-12-21 18:41:53.000000000 +0100 ++++ linux-mips/arch/sparc64/lib/atomic.S 2005-03-26 11:47:19.671423210 +0100 +@@ -4,33 +4,83 @@ + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + ++#include <linux/config.h> + #include <asm/asi.h> + ++ /* On SMP we need to use memory barriers to ensure ++ * correct memory operation ordering, nop these out ++ * for uniprocessor. ++ */ ++#ifdef CONFIG_SMP ++#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad ++#define ATOMIC_POST_BARRIER membar #StoreLoad | #StoreStore ++#else ++#define ATOMIC_PRE_BARRIER nop ++#define ATOMIC_POST_BARRIER nop ++#endif ++ + .text +- .align 64 + + .globl atomic_impl_begin, atomic_impl_end +- +- .globl __atomic_add + atomic_impl_begin: +-__atomic_add: /* %o0 = increment, %o1 = atomic_ptr */ +- lduw [%o1], %g5 ++ /* Two versions of the atomic routines, one that ++ * does not return a value and does not perform ++ * memory barriers, and a second which returns ++ * a value and does the barriers. ++ */ ++ .globl atomic_add ++ .type atomic_add,#function ++atomic_add: /* %o0 = increment, %o1 = atomic_ptr */ ++1: lduw [%o1], %g5 ++ add %g5, %o0, %g7 ++ cas [%o1], %g5, %g7 ++ cmp %g5, %g7 ++ bne,pn %icc, 1b ++ nop ++ retl ++ nop ++ .size atomic_add, .-atomic_add ++ ++ .globl atomic_sub ++ .type atomic_sub,#function ++atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ ++1: lduw [%o1], %g5 ++ sub %g5, %o0, %g7 ++ cas [%o1], %g5, %g7 ++ cmp %g5, %g7 ++ bne,pn %icc, 1b ++ nop ++ retl ++ nop ++ .size atomic_sub, .-atomic_sub ++ ++ .globl atomic_add_ret ++ .type atomic_add_ret,#function ++atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ ++ ATOMIC_PRE_BARRIER ++1: lduw [%o1], %g5 + add %g5, %o0, %g7 + cas [%o1], %g5, %g7 + cmp %g5, %g7 +- bne,pn %icc, __atomic_add +- membar #StoreLoad | #StoreStore ++ bne,pn %icc, 1b ++ add %g7, %o0, %g7 ++ ATOMIC_POST_BARRIER + retl +- add %g7, %o0, %o0 ++ sra %g7, 0, %o0 ++ .size atomic_add_ret, .-atomic_add_ret + +- .globl __atomic_sub +-__atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */ +- lduw [%o1], %g5 ++ .globl atomic_sub_ret ++ .type atomic_sub_ret,#function ++atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ ++ ATOMIC_PRE_BARRIER ++1: lduw [%o1], %g5 + sub %g5, %o0, %g7 + cas [%o1], %g5, %g7 + cmp %g5, %g7 +- bne,pn %icc, __atomic_sub +- membar #StoreLoad | #StoreStore ++ bne,pn %icc, 1b ++ sub %g7, %o0, %g7 ++ ATOMIC_POST_BARRIER + retl +- sub %g7, %o0, %o0 ++ sra %g7, 0, %o0 ++ .size atomic_sub_ret, .-atomic_sub_ret + atomic_impl_end: +diff -Nur linux-2.4.29/arch/sparc64/lib/bitops.S linux-mips/arch/sparc64/lib/bitops.S +--- linux-2.4.29/arch/sparc64/lib/bitops.S 2001-12-21 18:41:53.000000000 +0100 ++++ linux-mips/arch/sparc64/lib/bitops.S 2005-03-26 11:47:19.683421241 +0100 +@@ -4,107 +4,149 @@ + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + */ + ++#include <linux/config.h> + #include <asm/asi.h> + ++ /* On SMP we need to use memory barriers to ensure ++ * correct memory operation ordering, nop these out ++ * for uniprocessor. ++ */ ++#ifdef CONFIG_SMP ++#define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad ++#define BITOP_POST_BARRIER membar #StoreLoad | #StoreStore ++#else ++#define BITOP_PRE_BARRIER nop ++#define BITOP_POST_BARRIER nop ++#endif ++ + .text +- .align 64 ++ + .globl __bitops_begin + __bitops_begin: + +- .globl ___test_and_set_bit +-___test_and_set_bit: /* %o0=nr, %o1=addr */ ++ ++ .globl test_and_set_bit ++ .type test_and_set_bit,#function ++test_and_set_bit: /* %o0=nr, %o1=addr */ ++ BITOP_PRE_BARRIER + srlx %o0, 6, %g1 + mov 1, %g5 + sllx %g1, 3, %g3 + and %o0, 63, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 +- ldx [%o1], %g7 +-1: andcc %g7, %g5, %o0 +- bne,pn %xcc, 2f +- xor %g7, %g5, %g1 ++1: ldx [%o1], %g7 ++ or %g7, %g5, %g1 + casx [%o1], %g7, %g1 + cmp %g7, %g1 +- bne,a,pn %xcc, 1b +- ldx [%o1], %g7 +-2: retl +- membar #StoreLoad | #StoreStore +- +- .globl ___test_and_clear_bit +-___test_and_clear_bit: /* %o0=nr, %o1=addr */ ++ bne,pn %xcc, 1b ++ and %g7, %g5, %g2 ++ BITOP_POST_BARRIER ++ clr %o0 ++ retl ++ movrne %g2, 1, %o0 ++ .size test_and_set_bit, .-test_and_set_bit ++ ++ .globl test_and_clear_bit ++ .type test_and_clear_bit,#function ++test_and_clear_bit: /* %o0=nr, %o1=addr */ ++ BITOP_PRE_BARRIER + srlx %o0, 6, %g1 + mov 1, %g5 + sllx %g1, 3, %g3 + and %o0, 63, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 +- ldx [%o1], %g7 +-1: andcc %g7, %g5, %o0 +- be,pn %xcc, 2f +- xor %g7, %g5, %g1 ++1: ldx [%o1], %g7 ++ andn %g7, %g5, %g1 + casx [%o1], %g7, %g1 + cmp %g7, %g1 +- bne,a,pn %xcc, 1b +- ldx [%o1], %g7 +-2: retl +- membar #StoreLoad | #StoreStore +- +- .globl ___test_and_change_bit +-___test_and_change_bit: /* %o0=nr, %o1=addr */ ++ bne,pn %xcc, 1b ++ and %g7, %g5, %g2 ++ BITOP_POST_BARRIER ++ clr %o0 ++ retl ++ movrne %g2, 1, %o0 ++ .size test_and_clear_bit, .-test_and_clear_bit ++ ++ .globl test_and_change_bit ++ .type test_and_change_bit,#function ++test_and_change_bit: /* %o0=nr, %o1=addr */ ++ BITOP_PRE_BARRIER ++ srlx %o0, 6, %g1 ++ mov 1, %g5 ++ sllx %g1, 3, %g3 ++ and %o0, 63, %g2 ++ sllx %g5, %g2, %g5 ++ add %o1, %g3, %o1 ++1: ldx [%o1], %g7 ++ xor %g7, %g5, %g1 ++ casx [%o1], %g7, %g1 ++ cmp %g7, %g1 ++ bne,pn %xcc, 1b ++ and %g7, %g5, %g2 ++ BITOP_POST_BARRIER ++ clr %o0 ++ retl ++ movrne %g2, 1, %o0 ++ .size test_and_change_bit, .-test_and_change_bit ++ ++ .globl set_bit ++ .type set_bit,#function ++set_bit: /* %o0=nr, %o1=addr */ ++ srlx %o0, 6, %g1 ++ mov 1, %g5 ++ sllx %g1, 3, %g3 ++ and %o0, 63, %g2 ++ sllx %g5, %g2, %g5 ++ add %o1, %g3, %o1 ++1: ldx [%o1], %g7 ++ or %g7, %g5, %g1 ++ casx [%o1], %g7, %g1 ++ cmp %g7, %g1 ++ bne,pn %xcc, 1b ++ nop ++ retl ++ nop ++ .size set_bit, .-set_bit ++ ++ .globl clear_bit ++ .type clear_bit,#function ++clear_bit: /* %o0=nr, %o1=addr */ ++ srlx %o0, 6, %g1 ++ mov 1, %g5 ++ sllx %g1, 3, %g3 ++ and %o0, 63, %g2 ++ sllx %g5, %g2, %g5 ++ add %o1, %g3, %o1 ++1: ldx [%o1], %g7 ++ andn %g7, %g5, %g1 ++ casx [%o1], %g7, %g1 ++ cmp %g7, %g1 ++ bne,pn %xcc, 1b ++ nop ++ retl ++ nop ++ .size clear_bit, .-clear_bit ++ ++ .globl change_bit ++ .type change_bit,#function ++change_bit: /* %o0=nr, %o1=addr */ + srlx %o0, 6, %g1 + mov 1, %g5 + sllx %g1, 3, %g3 + and %o0, 63, %g2 + sllx %g5, %g2, %g5 + add %o1, %g3, %o1 +- ldx [%o1], %g7 +-1: and %g7, %g5, %o0 ++1: ldx [%o1], %g7 + xor %g7, %g5, %g1 + casx [%o1], %g7, %g1 + cmp %g7, %g1 +- bne,a,pn %xcc, 1b +- ldx [%o1], %g7 +-2: retl +- membar #StoreLoad | #StoreStore - nop -+ mtc0_tlbw_hazard - tlbwr -- rm9000_tlb_hazard -+ tlbw_eret_hazard - eret - END(handle_vec1_r10k) +- +- .globl ___test_and_set_le_bit +-___test_and_set_le_bit: /* %o0=nr, %o1=addr */ +- srlx %o0, 5, %g1 +- mov 1, %g5 +- sllx %g1, 2, %g3 +- and %o0, 31, %g2 +- sllx %g5, %g2, %g5 +- add %o1, %g3, %o1 +- lduwa [%o1] ASI_PL, %g7 +-1: andcc %g7, %g5, %o0 +- bne,pn %icc, 2f +- xor %g7, %g5, %g1 +- casa [%o1] ASI_PL, %g7, %g1 +- cmp %g7, %g1 +- bne,a,pn %icc, 1b +- lduwa [%o1] ASI_PL, %g7 +-2: retl +- membar #StoreLoad | #StoreStore +- +- .globl ___test_and_clear_le_bit +-___test_and_clear_le_bit: /* %o0=nr, %o1=addr */ +- srlx %o0, 5, %g1 +- mov 1, %g5 +- sllx %g1, 2, %g3 +- and %o0, 31, %g2 +- sllx %g5, %g2, %g5 +- add %o1, %g3, %o1 +- lduwa [%o1] ASI_PL, %g7 +-1: andcc %g7, %g5, %o0 +- be,pn %icc, 2f +- xor %g7, %g5, %g1 +- casa [%o1] ASI_PL, %g7, %g1 +- cmp %g7, %g1 +- bne,a,pn %icc, 1b +- lduwa [%o1] ASI_PL, %g7 +-2: retl +- membar #StoreLoad | #StoreStore ++ bne,pn %xcc, 1b ++ nop ++ retl ++ nop ++ .size change_bit, .-change_bit + + .globl __bitops_end + __bitops_end: +diff -Nur linux-2.4.29/arch/sparc64/lib/debuglocks.c linux-mips/arch/sparc64/lib/debuglocks.c +--- linux-2.4.29/arch/sparc64/lib/debuglocks.c 2001-12-21 18:41:53.000000000 +0100 ++++ linux-mips/arch/sparc64/lib/debuglocks.c 2005-03-26 11:47:19.684421077 +0100 +@@ -162,6 +162,7 @@ + runlock_again: + /* Spin trying to decrement the counter using casx. */ + __asm__ __volatile__( ++" membar #StoreLoad | #LoadLoad\n" + " ldx [%0], %%g5\n" + " sub %%g5, 1, %%g7\n" + " casx [%0], %%g5, %%g7\n" +@@ -276,6 +277,7 @@ + current->thread.smp_lock_count--; + wlock_again: + __asm__ __volatile__( ++" membar #StoreLoad | #LoadLoad\n" + " mov 1, %%g3\n" + " sllx %%g3, 63, %%g3\n" + " ldx [%0], %%g5\n" +diff -Nur linux-2.4.29/arch/sparc64/lib/rwlock.S linux-mips/arch/sparc64/lib/rwlock.S +--- linux-2.4.29/arch/sparc64/lib/rwlock.S 2000-09-09 02:55:17.000000000 +0200 ++++ linux-mips/arch/sparc64/lib/rwlock.S 2005-03-26 11:47:19.689420256 +0100 +@@ -24,12 +24,13 @@ + 99: retl + nop + __read_unlock: /* %o0 = lock_ptr */ ++ membar #StoreLoad | #LoadLoad + lduw [%o0], %g5 + sub %g5, 1, %g7 + cas [%o0], %g5, %g7 + cmp %g5, %g7 + be,pt %xcc, 99b +- membar #StoreLoad | #StoreStore ++ nop + ba,a,pt %xcc, __read_unlock + + __read_wait_for_writer: +diff -Nur linux-2.4.29/arch/x86_64/ia32/socket32.c linux-mips/arch/x86_64/ia32/socket32.c +--- linux-2.4.29/arch/x86_64/ia32/socket32.c 2005-01-19 15:09:39.000000000 +0100 ++++ linux-mips/arch/x86_64/ia32/socket32.c 2005-03-26 11:47:19.905384811 +0100 +@@ -302,7 +302,8 @@ + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) ++static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, ++ unsigned long orig_cmsg_uptr, __kernel_size_t orig_cmsg_len) + { + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; +@@ -333,6 +334,9 @@ + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; ++ if ((clen64 < CMSG_ALIGN(sizeof(*ucmsg))) || ++ (clen64 > (orig_cmsg_len + wp - workbuf))) ++ break; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + +@@ -418,6 +422,7 @@ + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; ++ __kernel_size_t cmsg_len; + int err, total_len, len = 0; + + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) +@@ -433,6 +438,7 @@ + total_len = err; + + cmsg_ptr = (unsigned long) kern_msg.msg_control; ++ cmsg_len = kern_msg.msg_controllen; + kern_msg.msg_flags = 0; + + sock = sockfd_lookup(fd, &err); +@@ -458,7 +464,8 @@ + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) +- cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); ++ cmsg32_recvmsg_fixup(&kern_msg, ++ cmsg_ptr, cmsg_len); + + /* Wheee... */ + if(sock->passcred) +diff -Nur linux-2.4.29/arch/x86_64/kernel/acpi.c linux-mips/arch/x86_64/kernel/acpi.c +--- linux-2.4.29/arch/x86_64/kernel/acpi.c 2004-08-08 01:26:04.000000000 +0200 ++++ linux-mips/arch/x86_64/kernel/acpi.c 2005-03-26 11:47:19.976373161 +0100 +@@ -53,6 +53,7 @@ -diff -Nur linux-2.4.29/drivers/char/Config.in linux-mips/drivers/char/Config.in ---- linux-2.4.29/drivers/char/Config.in 2004-08-08 01:26:04.000000000 +0200 -+++ linux-mips/drivers/char/Config.in 2005-02-12 04:06:18.000000000 +0100 -@@ -313,14 +313,11 @@ - if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then - bool 'Tadpole ANA H8 Support (OBSOLETE)' CONFIG_H8 - fi --if [ "$CONFIG_MIPS" = "y" -a "$CONFIG_NEW_TIME_C" = "y" ]; then -- tristate 'Generic MIPS RTC Support' CONFIG_MIPS_RTC --fi - if [ "$CONFIG_SGI_IP22" = "y" ]; then -- bool 'SGI DS1286 RTC support' CONFIG_SGI_DS1286 -+ tristate 'Dallas DS1286 RTC support' CONFIG_DS1286 - fi - if [ "$CONFIG_SGI_IP27" = "y" ]; then -- bool 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC -+ tristate 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC - fi - if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then - tristate 'Dallas DS1742 RTC support' CONFIG_DS1742 -@@ -383,6 +380,11 @@ - source drivers/char/drm/Config.in - fi - fi + acpi_interrupt_flags acpi_sci_flags __initdata; + int acpi_sci_override_gsi __initdata; ++int acpi_skip_timer_override __initdata; + /* -------------------------------------------------------------------------- + Boot-time Configuration + -------------------------------------------------------------------------- */ +@@ -333,6 +334,12 @@ + return 0; + } + ++ if (acpi_skip_timer_override && ++ intsrc->bus_irq == 0 && intsrc->global_irq == 2) { ++ printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); ++ return 0; ++ } + -+if [ "$CONFIG_X86" = "y" ]; then -+ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE -+fi + mp_override_legacy_irq ( + intsrc->bus_irq, + intsrc->flags.polarity, +diff -Nur linux-2.4.29/arch/x86_64/kernel/io_apic.c linux-mips/arch/x86_64/kernel/io_apic.c +--- linux-2.4.29/arch/x86_64/kernel/io_apic.c 2004-08-08 01:26:04.000000000 +0200 ++++ linux-mips/arch/x86_64/kernel/io_apic.c 2005-03-26 11:47:19.977372996 +0100 +@@ -259,10 +259,14 @@ + case PCI_VENDOR_ID_VIA: + return; + case PCI_VENDOR_ID_NVIDIA: ++#ifdef CONFIG_ACPI ++ /* All timer overrides on Nvidia ++ seem to be wrong. Skip them. */ ++ acpi_skip_timer_override = 1; + printk(KERN_INFO +- "PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n", +- num,slot,vendor); +- skip_ioapic_setup = 1; ++ "Nvidia board detected. Ignoring ACPI timer override.\n"); ++#endif ++ /* RED-PEN skip them on mptables too? */ + return; + } + +diff -Nur linux-2.4.29/arch/x86_64/kernel/pci-irq.c linux-mips/arch/x86_64/kernel/pci-irq.c +--- linux-2.4.29/arch/x86_64/kernel/pci-irq.c 2003-08-25 13:44:40.000000000 +0200 ++++ linux-mips/arch/x86_64/kernel/pci-irq.c 2005-03-26 11:47:20.061359212 +0100 +@@ -742,7 +742,7 @@ + void pcibios_enable_irq(struct pci_dev *dev) + { + u8 pin; +- extern int interrupt_line_quirk; ++ extern int via_interrupt_line_quirk; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { +@@ -762,6 +762,6 @@ + } + /* VIA bridges use interrupt line for apic/pci steering across + the V-Link */ +- else if (interrupt_line_quirk) ++ else if (via_interrupt_line_quirk) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +diff -Nur linux-2.4.29/arch/x86_64/kernel/setup.c linux-mips/arch/x86_64/kernel/setup.c +--- linux-2.4.29/arch/x86_64/kernel/setup.c 2005-01-19 15:09:39.000000000 +0100 ++++ linux-mips/arch/x86_64/kernel/setup.c 2005-03-26 11:47:20.069357900 +0100 +@@ -93,7 +93,8 @@ + struct resource standard_io_resources[] = { + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, + { "pic1", 0x20, 0x3f, IORESOURCE_BUSY }, +- { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, ++ { "timer0", 0x40, 0x43, IORESOURCE_BUSY }, ++ { "timer1", 0x50, 0x53, IORESOURCE_BUSY }, + { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, + { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY }, +diff -Nur linux-2.4.29/Documentation/Changes linux-mips/Documentation/Changes +--- linux-2.4.29/Documentation/Changes 2005-01-19 15:09:22.000000000 +0100 ++++ linux-mips/Documentation/Changes 2005-03-26 11:47:05.688718095 +0100 +@@ -341,7 +341,7 @@ + + JFSutils + --------- +-o <http://oss.software.ibm.com/jfs/> ++o <http://jfs.sourceforge.net/> + + Reiserfsprogs + ------------- +diff -Nur linux-2.4.29/Documentation/Configure.help linux-mips/Documentation/Configure.help +--- linux-2.4.29/Documentation/Configure.help 2005-01-19 15:09:22.000000000 +0100 ++++ linux-mips/Documentation/Configure.help 2005-03-26 11:47:12.272637522 +0100 +@@ -9345,6 +9345,11 @@ + + If unsure, say N. + ++CONFIG_SCSI_SATA_QSTOR ++ This option enables support for Pacific Digital Serial ATA QStor. ++ ++ If unsure, say N. ++ + CONFIG_SCSI_SATA_SX4 + This option enables support for Promise Serial ATA SX4. + +diff -Nur linux-2.4.29/Documentation/filesystems/jfs.txt linux-mips/Documentation/filesystems/jfs.txt +--- linux-2.4.29/Documentation/filesystems/jfs.txt 2003-11-28 19:26:19.000000000 +0100 ++++ linux-mips/Documentation/filesystems/jfs.txt 2005-03-26 11:47:12.320629645 +0100 +@@ -1,13 +1,6 @@ + IBM's Journaled File System (JFS) for Linux + +-JFS Homepage: http://oss.software.ibm.com/jfs/ +- +-Team members +------------- +-Dave Kleikamp shaggy@austin.ibm.com +-Dave Blaschke blaschke@us.ibm.com +-Steve Best sbest@us.ibm.com +-Barry Arndt barndt@us.ibm.com ++JFS Homepage: http://jfs.sourceforge.net/ + + The following mount options are supported: + +@@ -15,7 +8,8 @@ + ASCII. The default is compiled into the kernel as + CONFIG_NLS_DEFAULT. Use iocharset=utf8 for UTF8 + translations. This requires CONFIG_NLS_UTF8 to be set +- in the kernel .config file. ++ in the kernel .config file. Specify iocharset=none for ++ no conversion (default linux-2.6 behavior). + + resize=value Resize the volume to <value> blocks. JFS only supports + growing a volume, not shrinking it. This option is only +@@ -51,4 +45,4 @@ + Please send bugs, comments, cards and letters to shaggy@austin.ibm.com. + + The JFS mailing list can be subscribed to by using the link labeled +-"Mail list Subscribe" at our web page http://oss.software.ibm.com/jfs/. ++"Mail list Subscribe" at our web page http://jfs.sourceforge.net/. +diff -Nur linux-2.4.29/Documentation/i2c/writing-clients linux-mips/Documentation/i2c/writing-clients +--- linux-2.4.29/Documentation/i2c/writing-clients 2004-11-17 12:54:20.000000000 +0100 ++++ linux-mips/Documentation/i2c/writing-clients 2005-03-26 11:47:12.338626691 +0100 +@@ -380,9 +380,6 @@ + + For now, you can ignore the `flags' parameter. It is there for future use. + +- /* Unique ID allocation */ +- static int foo_id = 0; +- + int foo_detect_client(struct i2c_adapter *adapter, int address, + unsigned short flags, int kind) + { +@@ -518,7 +515,6 @@ + data->type = kind; + /* SENSORS ONLY END */ + +- new_client->id = foo_id++; /* Automatically unique */ + data->valid = 0; /* Only if you use this field */ + init_MUTEX(&data->update_lock); /* Only if you use this field */ + +diff -Nur linux-2.4.29/drivers/acpi/pci_irq.c linux-mips/drivers/acpi/pci_irq.c +--- linux-2.4.29/drivers/acpi/pci_irq.c 2004-08-08 01:26:04.000000000 +0200 ++++ linux-mips/drivers/acpi/pci_irq.c 2005-03-26 11:47:20.083355602 +0100 +@@ -335,6 +335,7 @@ + { + int irq = 0; + u8 pin = 0; ++ extern int via_interrupt_line_quirk; + + ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); + +@@ -383,6 +384,9 @@ + } + } + ++ if (via_interrupt_line_quirk) ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15); + - endmenu + dev->irq = irq; - if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then -@@ -391,6 +393,7 @@ - if [ "$CONFIG_SOC_AU1X00" = "y" ]; then - tristate ' Alchemy Au1x00 GPIO device support' CONFIG_AU1X00_GPIO - tristate ' Au1000/ADS7846 touchscreen support' CONFIG_TS_AU1X00_ADS7846 -+ #tristate ' Alchemy Au1550 PSC SPI support' CONFIG_AU1550_PSC_SPI - fi - if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then - tristate ' ITE GPIO' CONFIG_ITE_GPIO -diff -Nur linux-2.4.29/drivers/char/Makefile linux-mips/drivers/char/Makefile ---- linux-2.4.29/drivers/char/Makefile 2004-08-08 01:26:04.000000000 +0200 -+++ linux-mips/drivers/char/Makefile 2005-02-12 04:06:18.000000000 +0100 -@@ -48,7 +48,12 @@ - KEYBD = - endif - ifeq ($(CONFIG_VR41XX_KIU),y) -- KEYMAP = -+ ifeq ($(CONFIG_IBM_WORKPAD),y) -+ KEYMAP = ibm_workpad_keymap.o -+ endif -+ ifeq ($(CONFIG_VICTOR_MPC30X),y) -+ KEYMAP = victor_mpc30x_keymap.o -+ endif - KEYBD = vr41xx_keyb.o - endif - endif -@@ -251,7 +256,6 @@ - obj-$(CONFIG_RTC) += rtc.o - obj-$(CONFIG_GEN_RTC) += genrtc.o - obj-$(CONFIG_EFI_RTC) += efirtc.o --obj-$(CONFIG_SGI_DS1286) += ds1286.o - obj-$(CONFIG_MIPS_RTC) += mips_rtc.o - obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o - ifeq ($(CONFIG_PPC),) -@@ -259,6 +263,7 @@ - endif - obj-$(CONFIG_TOSHIBA) += toshiba.o - obj-$(CONFIG_I8K) += i8k.o -+obj-$(CONFIG_DS1286) += ds1286.o - obj-$(CONFIG_DS1620) += ds1620.o - obj-$(CONFIG_DS1742) += ds1742.o - obj-$(CONFIG_INTEL_RNG) += i810_rng.o -@@ -269,6 +274,7 @@ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", dev->slot_name, dev->irq)); +diff -Nur linux-2.4.29/drivers/block/nbd.c linux-mips/drivers/block/nbd.c +--- linux-2.4.29/drivers/block/nbd.c 2003-08-25 13:44:41.000000000 +0200 ++++ linux-mips/drivers/block/nbd.c 2005-03-26 11:47:20.373308014 +0100 +@@ -408,10 +408,7 @@ + int dev, error, temp; + struct request sreq ; - obj-$(CONFIG_ITE_GPIO) += ite_gpio.o - obj-$(CONFIG_AU1X00_GPIO) += au1000_gpio.o -+obj-$(CONFIG_AU1550_PSC_SPI) += au1550_psc_spi.o - obj-$(CONFIG_AU1X00_USB_TTY) += au1000_usbtty.o - obj-$(CONFIG_AU1X00_USB_RAW) += au1000_usbraw.o - obj-$(CONFIG_COBALT_LCD) += lcd.o -@@ -353,3 +359,9 @@ +- /* Anyone capable of this syscall can do *real bad* things */ - qtronixmap.c: qtronixmap.map - set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ +- if (!capable(CAP_SYS_ADMIN)) +- return -EPERM; + if (!inode) + return -EINVAL; + dev = MINOR(inode->i_rdev); +@@ -419,6 +416,20 @@ + return -ENODEV; + + lo = &nbd_dev[dev]; + -+ibm_workpad_keymap.c: ibm_workpad_keymap.map -+ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ++ /* these are innocent, but.... */ ++ switch (cmd) { ++ case BLKGETSIZE: ++ return put_user(nbd_bytesizes[dev] >> 9, (unsigned long *) arg); ++ case BLKGETSIZE64: ++ return put_user((u64)nbd_bytesizes[dev], (u64 *) arg); ++ } + -+victor_mpc30x_keymap.c: victor_mpc30x_keymap.map -+ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ++ /* ... anyone capable of any of the below ioctls can do *real bad* ++ things */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + switch (cmd) { + case NBD_DISCONNECT: + printk("NBD_DISCONNECT\n"); +@@ -524,10 +535,6 @@ + dev, lo->queue_head.next, lo->queue_head.prev, requests_in, requests_out); + return 0; + #endif +- case BLKGETSIZE: +- return put_user(nbd_bytesizes[dev] >> 9, (unsigned long *) arg); +- case BLKGETSIZE64: +- return put_user((u64)nbd_bytesizes[dev], (u64 *) arg); + } + return -EINVAL; + } diff -Nur linux-2.4.29/drivers/char/au1000_gpio.c linux-mips/drivers/char/au1000_gpio.c --- linux-2.4.29/drivers/char/au1000_gpio.c 2003-08-25 13:44:41.000000000 +0200 +++ linux-mips/drivers/char/au1000_gpio.c 2003-12-20 14:18:51.000000000 +0100 @@ -10088,7 +13440,7 @@ diff -Nur linux-2.4.29/drivers/char/au1000_gpio.c linux-mips/drivers/char/au1000 }; diff -Nur linux-2.4.29/drivers/char/au1550_psc_spi.c linux-mips/drivers/char/au1550_psc_spi.c --- linux-2.4.29/drivers/char/au1550_psc_spi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/drivers/char/au1550_psc_spi.c 2005-02-12 04:06:18.000000000 +0100 ++++ linux-mips/drivers/char/au1550_psc_spi.c 2005-03-26 11:47:20.510285533 +0100 @@ -0,0 +1,466 @@ +/* + * Driver for Alchemy Au1550 SPI on the PSC. @@ -10556,6 +13908,46 @@ diff -Nur linux-2.4.29/drivers/char/au1550_psc_spi.c linux-mips/drivers/char/au1 + +module_init(au1550spi_init); +module_exit(au1550spi_exit); +diff -Nur linux-2.4.29/drivers/char/Config.in linux-mips/drivers/char/Config.in +--- linux-2.4.29/drivers/char/Config.in 2004-08-08 01:26:04.000000000 +0200 ++++ linux-mips/drivers/char/Config.in 2005-03-26 11:47:20.469292261 +0100 +@@ -313,14 +313,11 @@ + if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then + bool 'Tadpole ANA H8 Support (OBSOLETE)' CONFIG_H8 + fi +-if [ "$CONFIG_MIPS" = "y" -a "$CONFIG_NEW_TIME_C" = "y" ]; then +- tristate 'Generic MIPS RTC Support' CONFIG_MIPS_RTC +-fi + if [ "$CONFIG_SGI_IP22" = "y" ]; then +- bool 'SGI DS1286 RTC support' CONFIG_SGI_DS1286 ++ tristate 'Dallas DS1286 RTC support' CONFIG_DS1286 + fi + if [ "$CONFIG_SGI_IP27" = "y" ]; then +- bool 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC ++ tristate 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC + fi + if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then + tristate 'Dallas DS1742 RTC support' CONFIG_DS1742 +@@ -383,6 +380,11 @@ + source drivers/char/drm/Config.in + fi + fi ++ ++if [ "$CONFIG_X86" = "y" ]; then ++ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE ++fi ++ + endmenu + + if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then +@@ -391,6 +393,7 @@ + if [ "$CONFIG_SOC_AU1X00" = "y" ]; then + tristate ' Alchemy Au1x00 GPIO device support' CONFIG_AU1X00_GPIO + tristate ' Au1000/ADS7846 touchscreen support' CONFIG_TS_AU1X00_ADS7846 ++ #tristate ' Alchemy Au1550 PSC SPI support' CONFIG_AU1550_PSC_SPI + fi + if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then + tristate ' ITE GPIO' CONFIG_ITE_GPIO diff -Nur linux-2.4.29/drivers/char/decserial.c linux-mips/drivers/char/decserial.c --- linux-2.4.29/drivers/char/decserial.c 2003-08-25 13:44:41.000000000 +0200 +++ linux-mips/drivers/char/decserial.c 2004-09-28 02:53:01.000000000 +0200 @@ -12544,6 +15936,120 @@ diff -Nur linux-2.4.29/drivers/char/ip27-rtc.c linux-mips/drivers/char/ip27-rtc. +MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); +MODULE_DESCRIPTION("SGI IP27 M48T35 RTC driver"); +MODULE_LICENSE("GPL"); +diff -Nur linux-2.4.29/drivers/char/lcd.c linux-mips/drivers/char/lcd.c +--- linux-2.4.29/drivers/char/lcd.c 2005-01-19 15:09:46.000000000 +0100 ++++ linux-mips/drivers/char/lcd.c 2005-03-26 11:47:20.582273718 +0100 +@@ -386,6 +386,8 @@ + + int ctr=0; + ++ if (!capable(CAP_SYS_ADMIN)) return -EPERM; ++ + // Chip Erase Sequence + WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); + WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); +@@ -422,6 +424,8 @@ + + struct lcd_display display; + ++ if (!capable(CAP_SYS_ADMIN)) return -EPERM; ++ + if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) + return -EFAULT; + rom = (unsigned char *) kmalloc((128),GFP_ATOMIC); +@@ -434,8 +438,10 @@ + save_flags(flags); + for (i=0; i<FLASH_SIZE; i=i+128) { + +- if(copy_from_user(rom, display.RomImage + i, 128)) ++ if(copy_from_user(rom, display.RomImage + i, 128)) { ++ kfree(rom); + return -EFAULT; ++ } + burn_addr = kFlashBase + i; + cli(); + for ( index = 0; index < ( 128 ) ; index++ ) +diff -Nur linux-2.4.29/drivers/char/lp.c linux-mips/drivers/char/lp.c +--- linux-2.4.29/drivers/char/lp.c 2005-01-19 15:09:46.000000000 +0100 ++++ linux-mips/drivers/char/lp.c 2005-03-26 11:47:20.584273390 +0100 +@@ -314,12 +314,14 @@ + if (copy_size > LP_BUFFER_SIZE) + copy_size = LP_BUFFER_SIZE; + +- if (copy_from_user (kbuf, buf, copy_size)) +- return -EFAULT; +- + if (down_interruptible (&lp_table[minor].port_mutex)) + return -EINTR; + ++ if (copy_from_user (kbuf, buf, copy_size)) { ++ retv = -EFAULT; ++ goto out_unlock; ++ } ++ + /* Claim Parport or sleep until it becomes available + */ + lp_claim_parport_or_block (&lp_table[minor]); +@@ -398,7 +400,7 @@ + lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; + lp_release_parport (&lp_table[minor]); + } +- ++out_unlock: + up (&lp_table[minor].port_mutex); + + return retv; +diff -Nur linux-2.4.29/drivers/char/Makefile linux-mips/drivers/char/Makefile +--- linux-2.4.29/drivers/char/Makefile 2004-08-08 01:26:04.000000000 +0200 ++++ linux-mips/drivers/char/Makefile 2005-03-26 11:47:20.471291933 +0100 +@@ -48,7 +48,12 @@ + KEYBD = + endif + ifeq ($(CONFIG_VR41XX_KIU),y) +- KEYMAP = ++ ifeq ($(CONFIG_IBM_WORKPAD),y) ++ KEYMAP = ibm_workpad_keymap.o ++ endif ++ ifeq ($(CONFIG_VICTOR_MPC30X),y) ++ KEYMAP = victor_mpc30x_keymap.o ++ endif + KEYBD = vr41xx_keyb.o + endif + endif +@@ -251,7 +256,6 @@ + obj-$(CONFIG_RTC) += rtc.o + obj-$(CONFIG_GEN_RTC) += genrtc.o + obj-$(CONFIG_EFI_RTC) += efirtc.o +-obj-$(CONFIG_SGI_DS1286) += ds1286.o + obj-$(CONFIG_MIPS_RTC) += mips_rtc.o + obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o + ifeq ($(CONFIG_PPC),) +@@ -259,6 +263,7 @@ + endif + obj-$(CONFIG_TOSHIBA) += toshiba.o + obj-$(CONFIG_I8K) += i8k.o ++obj-$(CONFIG_DS1286) += ds1286.o + obj-$(CONFIG_DS1620) += ds1620.o + obj-$(CONFIG_DS1742) += ds1742.o + obj-$(CONFIG_INTEL_RNG) += i810_rng.o +@@ -269,6 +274,7 @@ + + obj-$(CONFIG_ITE_GPIO) += ite_gpio.o + obj-$(CONFIG_AU1X00_GPIO) += au1000_gpio.o ++obj-$(CONFIG_AU1550_PSC_SPI) += au1550_psc_spi.o + obj-$(CONFIG_AU1X00_USB_TTY) += au1000_usbtty.o + obj-$(CONFIG_AU1X00_USB_RAW) += au1000_usbraw.o + obj-$(CONFIG_COBALT_LCD) += lcd.o +@@ -353,3 +359,9 @@ + + qtronixmap.c: qtronixmap.map + set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ++ ++ibm_workpad_keymap.c: ibm_workpad_keymap.map ++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ++ ++victor_mpc30x_keymap.c: victor_mpc30x_keymap.map ++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ diff -Nur linux-2.4.29/drivers/char/mips_rtc.c linux-mips/drivers/char/mips_rtc.c --- linux-2.4.29/drivers/char/mips_rtc.c 2004-01-05 14:53:56.000000000 +0100 +++ linux-mips/drivers/char/mips_rtc.c 2004-06-28 14:54:53.000000000 +0200 @@ -12667,6 +16173,34 @@ diff -Nur linux-2.4.29/drivers/char/serial.c linux-mips/drivers/char/serial.c /* * We used to support using pause I/O for certain machines. We +diff -Nur linux-2.4.29/drivers/char/synclinkmp.c linux-mips/drivers/char/synclinkmp.c +--- linux-2.4.29/drivers/char/synclinkmp.c 2005-01-19 15:09:53.000000000 +0100 ++++ linux-mips/drivers/char/synclinkmp.c 2005-03-26 11:47:20.653262067 +0100 +@@ -1,5 +1,5 @@ + /* +- * $Id$ ++ * $Id$ + * + * Device driver for Microgate SyncLink Multiport + * high speed multiprotocol serial adapter. +@@ -504,7 +504,7 @@ + MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); + + static char *driver_name = "SyncLink MultiPort driver"; +-static char *driver_version = "$Revision$"; ++static char *driver_version = "$Revision$"; + + static int __devinit synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); + static void __devexit synclinkmp_remove_one(struct pci_dev *dev); +@@ -4482,7 +4482,7 @@ + * 07..05 Reserved, must be 0 + * 04..00 RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte + */ +- write_reg(info, TRC0, 0x00); ++ write_reg(info, RRC, 0x00); + + /* TRC0 Transmit Ready Control 0 + * diff -Nur linux-2.4.29/drivers/char/victor_mpc30x_keymap.map linux-mips/drivers/char/victor_mpc30x_keymap.map --- linux-2.4.29/drivers/char/victor_mpc30x_keymap.map 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/drivers/char/victor_mpc30x_keymap.map 2004-02-05 18:04:42.000000000 +0100 @@ -12796,7 +16330,7 @@ diff -Nur linux-2.4.29/drivers/char/vr41xx_keyb.c linux-mips/drivers/char/vr41xx diff -Nur linux-2.4.29/drivers/i2c/Config.in linux-mips/drivers/i2c/Config.in --- linux-2.4.29/drivers/i2c/Config.in 2004-04-14 15:05:29.000000000 +0200 -+++ linux-mips/drivers/i2c/Config.in 2005-02-12 04:06:32.000000000 +0100 ++++ linux-mips/drivers/i2c/Config.in 2005-03-26 11:47:20.974209393 +0100 @@ -57,6 +57,10 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then dep_tristate 'I2C SGI interfaces' CONFIG_I2C_ALGO_SGI $CONFIG_I2C @@ -12808,29 +16342,9 @@ diff -Nur linux-2.4.29/drivers/i2c/Config.in linux-mips/drivers/i2c/Config.in # This is needed for automatic patch generation: sensors code starts here # This is needed for automatic patch generation: sensors code ends here -diff -Nur linux-2.4.29/drivers/i2c/Makefile linux-mips/drivers/i2c/Makefile ---- linux-2.4.29/drivers/i2c/Makefile 2004-02-18 14:36:31.000000000 +0100 -+++ linux-mips/drivers/i2c/Makefile 2005-02-12 04:06:32.000000000 +0100 -@@ -6,7 +6,7 @@ - - export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \ - i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \ -- i2c-proc.o -+ i2c-algo-au1550.o i2c-proc.o i2c-au1550.o - - obj-$(CONFIG_I2C) += i2c-core.o - obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o -@@ -25,6 +25,7 @@ - obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o i2c-sibyte.o - obj-$(CONFIG_I2C_MAX1617) += i2c-max1617.o - obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o -+obj-$(CONFIG_I2C_ALGO_AU1550) += i2c-algo-au1550.o i2c-au1550.o - - # This is needed for automatic patch generation: sensors code starts here - # This is needed for automatic patch generation: sensors code ends here diff -Nur linux-2.4.29/drivers/i2c/i2c-algo-au1550.c linux-mips/drivers/i2c/i2c-algo-au1550.c --- linux-2.4.29/drivers/i2c/i2c-algo-au1550.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/drivers/i2c/i2c-algo-au1550.c 2005-02-12 04:06:32.000000000 +0100 ++++ linux-mips/drivers/i2c/i2c-algo-au1550.c 2005-03-26 11:47:21.004204470 +0100 @@ -0,0 +1,340 @@ +/* + * i2c-algo-au1550.c: SMBus (i2c) driver algorithms for Alchemy PSC interface @@ -13172,9 +16686,70 @@ diff -Nur linux-2.4.29/drivers/i2c/i2c-algo-au1550.c linux-mips/drivers/i2c/i2c- +MODULE_AUTHOR("Dan Malek <dan@embeddededge.com>"); +MODULE_DESCRIPTION("SMBus Au1550 algorithm"); +MODULE_LICENSE("GPL"); +diff -Nur linux-2.4.29/drivers/i2c/i2c-algo-bit.c linux-mips/drivers/i2c/i2c-algo-bit.c +--- linux-2.4.29/drivers/i2c/i2c-algo-bit.c 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/i2c/i2c-algo-bit.c 2005-03-26 11:47:21.069193803 +0100 +@@ -28,14 +28,12 @@ + #include <linux/delay.h> + #include <linux/slab.h> + #include <linux/init.h> +-#include <asm/uaccess.h> +-#include <linux/ioport.h> + #include <linux/errno.h> + #include <linux/sched.h> +- + #include <linux/i2c.h> + #include <linux/i2c-algo-bit.h> + ++ + /* ----- global defines ----------------------------------------------- */ + #define DEB(x) if (i2c_debug>=1) x; + #define DEB2(x) if (i2c_debug>=2) x; +@@ -522,8 +520,8 @@ + + static u32 bit_func(struct i2c_adapter *adap) + { +- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | +- I2C_FUNC_PROTOCOL_MANGLING; ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | ++ I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; + } + + +diff -Nur linux-2.4.29/drivers/i2c/i2c-algo-pcf.c linux-mips/drivers/i2c/i2c-algo-pcf.c +--- linux-2.4.29/drivers/i2c/i2c-algo-pcf.c 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/i2c/i2c-algo-pcf.c 2005-03-26 11:47:21.128184122 +0100 +@@ -32,15 +32,13 @@ + #include <linux/delay.h> + #include <linux/slab.h> + #include <linux/init.h> +-#include <asm/uaccess.h> +-#include <linux/ioport.h> + #include <linux/errno.h> + #include <linux/sched.h> +- + #include <linux/i2c.h> + #include <linux/i2c-algo-pcf.h> + #include "i2c-pcf8584.h" + ++ + /* ----- global defines ----------------------------------------------- */ + #define DEB(x) if (i2c_debug>=1) x + #define DEB2(x) if (i2c_debug>=2) x +@@ -435,8 +433,8 @@ + + static u32 pcf_func(struct i2c_adapter *adap) + { +- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | +- I2C_FUNC_PROTOCOL_MANGLING; ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | ++ I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; + } + + /* -----exported algorithm data: ------------------------------------- */ diff -Nur linux-2.4.29/drivers/i2c/i2c-au1550.c linux-mips/drivers/i2c/i2c-au1550.c --- linux-2.4.29/drivers/i2c/i2c-au1550.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/drivers/i2c/i2c-au1550.c 2005-02-12 04:06:32.000000000 +0100 ++++ linux-mips/drivers/i2c/i2c-au1550.c 2005-03-26 11:47:21.146181168 +0100 @@ -0,0 +1,154 @@ +/* + * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface @@ -13354,6 +16929,115 @@ diff -Nur linux-2.4.29/drivers/i2c/i2c-core.c linux-mips/drivers/i2c/i2c-core.c /* -------------- proc interface ---- */ #ifdef CONFIG_I2C_PROC sensors_init(); +diff -Nur linux-2.4.29/drivers/i2c/Makefile linux-mips/drivers/i2c/Makefile +--- linux-2.4.29/drivers/i2c/Makefile 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/i2c/Makefile 2005-03-26 11:47:20.975209228 +0100 +@@ -6,7 +6,7 @@ + + export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \ + i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \ +- i2c-proc.o ++ i2c-algo-au1550.o i2c-proc.o i2c-au1550.o + + obj-$(CONFIG_I2C) += i2c-core.o + obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o +@@ -25,6 +25,7 @@ + obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o i2c-sibyte.o + obj-$(CONFIG_I2C_MAX1617) += i2c-max1617.o + obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o ++obj-$(CONFIG_I2C_ALGO_AU1550) += i2c-algo-au1550.o i2c-au1550.o + + # This is needed for automatic patch generation: sensors code starts here + # This is needed for automatic patch generation: sensors code ends here +diff -Nur linux-2.4.29/drivers/ide/ide-cd.c linux-mips/drivers/ide/ide-cd.c +--- linux-2.4.29/drivers/ide/ide-cd.c 2003-11-28 19:26:20.000000000 +0100 ++++ linux-mips/drivers/ide/ide-cd.c 2005-03-26 11:47:21.315153436 +0100 +@@ -2206,25 +2206,31 @@ + /* Read the multisession information. */ + if (toc->hdr.first_track != CDROM_LEADOUT) { + /* Read the multisession information. */ +- stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, ++ stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp, + sizeof(ms_tmp), sense); + if (stat) return stat; ++ ++ toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba); + } else { +- ms_tmp.ent.addr.msf.minute = 0; +- ms_tmp.ent.addr.msf.second = 2; +- ms_tmp.ent.addr.msf.frame = 0; + ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; ++ toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */ + } + + #if ! STANDARD_ATAPI +- if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) ++ if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) { ++ /* Re-read multisession information using MSF format */ ++ stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, ++ sizeof(ms_tmp), sense); ++ if (stat) ++ return stat; ++ + msf_from_bcd (&ms_tmp.ent.addr.msf); ++ toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute, ++ ms_tmp.ent.addr.msf.second, ++ ms_tmp.ent.addr.msf.frame); ++ } + #endif /* not STANDARD_ATAPI */ + +- toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute, +- ms_tmp.ent.addr.msf.second, +- ms_tmp.ent.addr.msf.frame); +- + toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); + + /* Now try to get the total cdrom capacity. */ +diff -Nur linux-2.4.29/drivers/isdn/hisax/ipacx.c linux-mips/drivers/isdn/hisax/ipacx.c +--- linux-2.4.29/drivers/isdn/hisax/ipacx.c 2002-11-29 00:53:13.000000000 +0100 ++++ linux-mips/drivers/isdn/hisax/ipacx.c 2005-03-26 11:47:21.653097971 +0100 +@@ -152,7 +152,13 @@ + + case (HW_RESET | REQUEST): + case (HW_ENABLE | REQUEST): +- ph_command(cs, IPACX_CMD_TIM); ++ if ((cs->dc.isac.ph_state == IPACX_IND_RES) || ++ (cs->dc.isac.ph_state == IPACX_IND_DR) || ++ (cs->dc.isac.ph_state == IPACX_IND_DC)) ++ ph_command(cs, IPACX_CMD_TIM); ++ else ++ ph_command(cs, IPACX_CMD_RES); ++ + break; + + case (HW_INFO3 | REQUEST): +diff -Nur linux-2.4.29/drivers/md/lvm-snap.c linux-mips/drivers/md/lvm-snap.c +--- linux-2.4.29/drivers/md/lvm-snap.c 2004-04-14 15:05:30.000000000 +0200 ++++ linux-mips/drivers/md/lvm-snap.c 2005-03-26 11:47:21.896058096 +0100 +@@ -119,7 +119,6 @@ + unsigned long mask = lv->lv_snapshot_hash_mask; + int chunk_size = lv->lv_chunk_size; + lv_block_exception_t *ret; +- int i = 0; + + hash_table = + &hash_table[hashfn(org_dev, org_start, mask, chunk_size)]; +@@ -132,15 +131,9 @@ + exception = list_entry(next, lv_block_exception_t, hash); + if (exception->rsector_org == org_start && + exception->rdev_org == org_dev) { +- if (i) { +- /* fun, isn't it? :) */ +- list_del(next); +- list_add(next, hash_table); +- } + ret = exception; + break; + } +- i++; + } + return ret; + } diff -Nur linux-2.4.29/drivers/media/video/indycam.c linux-mips/drivers/media/video/indycam.c --- linux-2.4.29/drivers/media/video/indycam.c 2004-02-18 14:36:31.000000000 +0100 +++ linux-mips/drivers/media/video/indycam.c 2004-12-09 21:32:05.000000000 +0100 @@ -13761,33 +17445,9 @@ diff -Nur linux-2.4.29/drivers/mtd/maps/Config.in linux-mips/drivers/mtd/maps/Co dep_tristate ' Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board' CONFIG_MTD_CSTM_MIPS_IXX $CONFIG_MTD_CFI $CONFIG_MTD_JEDEC $CONFIG_MTD_PARTITIONS if [ "$CONFIG_MTD_CSTM_MIPS_IXX" = "y" -o "$CONFIG_MTD_CSTM_MIPS_IXX" = "m" ]; then hex ' Physical start address of flash mapping' CONFIG_MTD_CSTM_MIPS_IXX_START 0x8000000 -diff -Nur linux-2.4.29/drivers/mtd/maps/Makefile linux-mips/drivers/mtd/maps/Makefile ---- linux-2.4.29/drivers/mtd/maps/Makefile 2003-06-13 16:51:34.000000000 +0200 -+++ linux-mips/drivers/mtd/maps/Makefile 2004-02-26 01:46:35.000000000 +0100 -@@ -52,7 +52,13 @@ - obj-$(CONFIG_MTD_PB1000) += pb1xxx-flash.o - obj-$(CONFIG_MTD_PB1100) += pb1xxx-flash.o - obj-$(CONFIG_MTD_PB1500) += pb1xxx-flash.o -+obj-$(CONFIG_MTD_XXS1500) += xxs1500.o -+obj-$(CONFIG_MTD_MTX1) += mtx-1.o - obj-$(CONFIG_MTD_LASAT) += lasat.o -+obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o -+obj-$(CONFIG_MTD_PB1550) += pb1550-flash.o -+obj-$(CONFIG_MTD_HYDROGEN3) += hydrogen3-flash.o -+obj-$(CONFIG_MTD_BOSPORUS) += pb1xxx-flash.o - obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o - obj-$(CONFIG_MTD_EDB7312) += edb7312.o - obj-$(CONFIG_MTD_IMPA7) += impa7.o -@@ -61,5 +67,6 @@ - obj-$(CONFIG_MTD_UCLINUX) += uclinux.o - obj-$(CONFIG_MTD_NETtel) += nettel.o - obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o -+obj-$(CONFIG_MTD_MIRAGE) += mirage-flash.o - - include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/drivers/mtd/maps/db1x00-flash.c linux-mips/drivers/mtd/maps/db1x00-flash.c --- linux-2.4.29/drivers/mtd/maps/db1x00-flash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/drivers/mtd/maps/db1x00-flash.c 2005-02-12 04:06:46.000000000 +0100 ++++ linux-mips/drivers/mtd/maps/db1x00-flash.c 2005-03-26 11:47:22.085027082 +0100 @@ -0,0 +1,283 @@ +/* + * Flash memory access on Alchemy Db1xxx boards @@ -14373,6 +18033,30 @@ diff -Nur linux-2.4.29/drivers/mtd/maps/lasat.c linux-mips/drivers/mtd/maps/lasa } } +diff -Nur linux-2.4.29/drivers/mtd/maps/Makefile linux-mips/drivers/mtd/maps/Makefile +--- linux-2.4.29/drivers/mtd/maps/Makefile 2003-06-13 16:51:34.000000000 +0200 ++++ linux-mips/drivers/mtd/maps/Makefile 2004-02-26 01:46:35.000000000 +0100 +@@ -52,7 +52,13 @@ + obj-$(CONFIG_MTD_PB1000) += pb1xxx-flash.o + obj-$(CONFIG_MTD_PB1100) += pb1xxx-flash.o + obj-$(CONFIG_MTD_PB1500) += pb1xxx-flash.o ++obj-$(CONFIG_MTD_XXS1500) += xxs1500.o ++obj-$(CONFIG_MTD_MTX1) += mtx-1.o + obj-$(CONFIG_MTD_LASAT) += lasat.o ++obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o ++obj-$(CONFIG_MTD_PB1550) += pb1550-flash.o ++obj-$(CONFIG_MTD_HYDROGEN3) += hydrogen3-flash.o ++obj-$(CONFIG_MTD_BOSPORUS) += pb1xxx-flash.o + obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o + obj-$(CONFIG_MTD_EDB7312) += edb7312.o + obj-$(CONFIG_MTD_IMPA7) += impa7.o +@@ -61,5 +67,6 @@ + obj-$(CONFIG_MTD_UCLINUX) += uclinux.o + obj-$(CONFIG_MTD_NETtel) += nettel.o + obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o ++obj-$(CONFIG_MTD_MIRAGE) += mirage-flash.o + + include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/drivers/mtd/maps/mirage-flash.c linux-mips/drivers/mtd/maps/mirage-flash.c --- linux-2.4.29/drivers/mtd/maps/mirage-flash.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/drivers/mtd/maps/mirage-flash.c 2003-12-22 04:37:22.000000000 +0100 @@ -16192,6 +19876,729 @@ diff -Nur linux-2.4.29/drivers/net/defxx.h linux-mips/drivers/net/defxx.h struct pci_dev * pci_dev; u32 full_duplex_enb; /* FDDI Full Duplex enable (1 == on, 2 == off) */ u32 req_ttrt; /* requested TTRT value (in 80ns units) */ +diff -Nur linux-2.4.29/drivers/net/e1000/e1000_ethtool.c linux-mips/drivers/net/e1000/e1000_ethtool.c +--- linux-2.4.29/drivers/net/e1000/e1000_ethtool.c 2005-01-19 15:09:56.000000000 +0100 ++++ linux-mips/drivers/net/e1000/e1000_ethtool.c 2005-03-26 11:47:31.355505582 +0100 +@@ -1309,7 +1309,7 @@ + struct e1000_desc_ring *txdr = &adapter->test_tx_ring; + struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; + struct pci_dev *pdev = adapter->pdev; +- int i; ++ int i, ret_val; + + E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); + +@@ -1329,11 +1329,12 @@ + rxdr->buffer_info[i].length, + PCI_DMA_FROMDEVICE); + +- if (!e1000_check_lbtest_frame(rxdr->buffer_info[i++].skb, 1024)) +- return 0; +- } while (i < 64); ++ ret_val = e1000_check_lbtest_frame(rxdr->buffer_info[i].skb, ++ 1024); ++ i++; ++ } while (ret_val != 0 && i < 64); + +- return 13; ++ return ret_val; + } + + static int +diff -Nur linux-2.4.29/drivers/net/e1000/e1000.h linux-mips/drivers/net/e1000/e1000.h +--- linux-2.4.29/drivers/net/e1000/e1000.h 2005-01-19 15:09:56.000000000 +0100 ++++ linux-mips/drivers/net/e1000/e1000.h 2005-03-26 11:47:30.488647853 +0100 +@@ -140,6 +140,7 @@ + #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ + + #define AUTO_ALL_MODES 0 ++#define E1000_EEPROM_82544_APM 0x0004 + #define E1000_EEPROM_APME 0x0400 + + #ifndef E1000_MASTER_SLAVE +@@ -211,6 +212,7 @@ + + /* TX */ + struct e1000_desc_ring tx_ring; ++ struct e1000_buffer previous_buffer_info; + spinlock_t tx_lock; + uint32_t txd_cmd; + uint32_t tx_int_delay; +@@ -224,6 +226,7 @@ + uint32_t tx_fifo_size; + atomic_t tx_fifo_stall; + boolean_t pcix_82544; ++ boolean_t detect_tx_hung; + + /* RX */ + struct e1000_desc_ring rx_ring; +diff -Nur linux-2.4.29/drivers/net/e1000/e1000_hw.c linux-mips/drivers/net/e1000/e1000_hw.c +--- linux-2.4.29/drivers/net/e1000/e1000_hw.c 2005-01-19 15:09:56.000000000 +0100 ++++ linux-mips/drivers/net/e1000/e1000_hw.c 2005-03-26 11:47:31.359504925 +0100 +@@ -1573,7 +1573,8 @@ + if(mii_status_reg & MII_SR_LINK_STATUS) break; + msec_delay(100); + } +- if((i == 0) && (hw->phy_type == e1000_phy_m88)) { ++ if((i == 0) && ++ (hw->phy_type == e1000_phy_m88)) { + /* We didn't get link. Reset the DSP and wait again for link. */ + ret_val = e1000_phy_reset_dsp(hw); + if(ret_val) { +@@ -2504,7 +2505,7 @@ + } + } + +- ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, ++ ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, + phy_data); + + return ret_val; +@@ -2610,7 +2611,7 @@ + } + } + +- ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, ++ ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, + phy_data); + + return ret_val; +@@ -2956,8 +2957,7 @@ + /* Check polarity status */ + ret_val = e1000_check_polarity(hw, &polarity); + if(ret_val) +- return ret_val; +- ++ return ret_val; + phy_info->cable_polarity = polarity; + + ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +@@ -2967,9 +2967,9 @@ + phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> + M88E1000_PSSR_MDIX_SHIFT; + +- if(phy_data & M88E1000_PSSR_1000MBS) { +- /* Cable Length Estimation and Local/Remote Receiver Informatoion +- * are only valid at 1000 Mbps ++ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { ++ /* Cable Length Estimation and Local/Remote Receiver Information ++ * are only valid at 1000 Mbps. + */ + phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT); +@@ -4641,41 +4641,44 @@ + { + uint32_t status; + +- if(hw->mac_type < e1000_82543) { ++ switch (hw->mac_type) { ++ case e1000_82542_rev2_0: ++ case e1000_82542_rev2_1: + hw->bus_type = e1000_bus_type_unknown; + hw->bus_speed = e1000_bus_speed_unknown; + hw->bus_width = e1000_bus_width_unknown; +- return; +- } +- +- status = E1000_READ_REG(hw, STATUS); +- hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? +- e1000_bus_type_pcix : e1000_bus_type_pci; ++ break; ++ default: ++ status = E1000_READ_REG(hw, STATUS); ++ hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? ++ e1000_bus_type_pcix : e1000_bus_type_pci; + +- if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { +- hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? +- e1000_bus_speed_66 : e1000_bus_speed_120; +- } else if(hw->bus_type == e1000_bus_type_pci) { +- hw->bus_speed = (status & E1000_STATUS_PCI66) ? +- e1000_bus_speed_66 : e1000_bus_speed_33; +- } else { +- switch (status & E1000_STATUS_PCIX_SPEED) { +- case E1000_STATUS_PCIX_SPEED_66: +- hw->bus_speed = e1000_bus_speed_66; +- break; +- case E1000_STATUS_PCIX_SPEED_100: +- hw->bus_speed = e1000_bus_speed_100; +- break; +- case E1000_STATUS_PCIX_SPEED_133: +- hw->bus_speed = e1000_bus_speed_133; +- break; +- default: +- hw->bus_speed = e1000_bus_speed_reserved; +- break; ++ if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { ++ hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? ++ e1000_bus_speed_66 : e1000_bus_speed_120; ++ } else if(hw->bus_type == e1000_bus_type_pci) { ++ hw->bus_speed = (status & E1000_STATUS_PCI66) ? ++ e1000_bus_speed_66 : e1000_bus_speed_33; ++ } else { ++ switch (status & E1000_STATUS_PCIX_SPEED) { ++ case E1000_STATUS_PCIX_SPEED_66: ++ hw->bus_speed = e1000_bus_speed_66; ++ break; ++ case E1000_STATUS_PCIX_SPEED_100: ++ hw->bus_speed = e1000_bus_speed_100; ++ break; ++ case E1000_STATUS_PCIX_SPEED_133: ++ hw->bus_speed = e1000_bus_speed_133; ++ break; ++ default: ++ hw->bus_speed = e1000_bus_speed_reserved; ++ break; ++ } + } ++ hw->bus_width = (status & E1000_STATUS_BUS64) ? ++ e1000_bus_width_64 : e1000_bus_width_32; ++ break; + } +- hw->bus_width = (status & E1000_STATUS_BUS64) ? +- e1000_bus_width_64 : e1000_bus_width_32; + } + /****************************************************************************** + * Reads a value from one of the devices registers using port I/O (as opposed +@@ -4740,6 +4743,7 @@ + uint16_t agc_value = 0; + uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; + uint16_t i, phy_data; ++ uint16_t cable_length; + + DEBUGFUNC("e1000_get_cable_length"); + +@@ -4751,10 +4755,11 @@ + &phy_data); + if(ret_val) + return ret_val; ++ cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> ++ M88E1000_PSSR_CABLE_LENGTH_SHIFT; + + /* Convert the enum value to ranged values */ +- switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> +- M88E1000_PSSR_CABLE_LENGTH_SHIFT) { ++ switch (cable_length) { + case e1000_cable_length_50: + *min_length = 0; + *max_length = e1000_igp_cable_length_50; +@@ -4921,8 +4926,7 @@ + return ret_val; + + hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; +- } +- else if(hw->phy_type == e1000_phy_m88) { ++ } else if(hw->phy_type == e1000_phy_m88) { + ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) +diff -Nur linux-2.4.29/drivers/net/e1000/e1000_hw.h linux-mips/drivers/net/e1000/e1000_hw.h +--- linux-2.4.29/drivers/net/e1000/e1000_hw.h 2005-01-19 15:09:56.000000000 +0100 ++++ linux-mips/drivers/net/e1000/e1000_hw.h 2005-03-26 11:47:31.362504433 +0100 +@@ -36,7 +36,6 @@ + #include "e1000_osdep.h" + + +- + /* Forward declarations of structures used by the shared code */ + struct e1000_hw; + struct e1000_hw_stats; +@@ -370,6 +369,7 @@ + #define E1000_DEV_ID_82546GB_SERDES 0x107B + #define E1000_DEV_ID_82546GB_PCIE 0x108A + #define E1000_DEV_ID_82547EI 0x1019 ++ + #define NODE_ADDRESS_SIZE 6 + #define ETH_LENGTH_OF_ADDRESS 6 + +@@ -1735,6 +1735,9 @@ + #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ + #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ + ++#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ ++#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */ ++ + /* M88E1000 Specific Registers */ + #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ + #define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ +@@ -1795,8 +1798,7 @@ + + #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 + +-#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ +-#define MAX_PHY_MULTI_PAGE_REG 0xF /*Registers that are equal on all pages*/ ++ + /* PHY Control Register */ + #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ + #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ +@@ -2099,7 +2101,11 @@ + #define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 + #define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 + ++ + /* Bit definitions for valid PHY IDs. */ ++/* I = Integrated ++ * E = External ++ */ + #define M88E1000_E_PHY_ID 0x01410C50 + #define M88E1000_I_PHY_ID 0x01410C30 + #define M88E1011_I_PHY_ID 0x01410C20 +diff -Nur linux-2.4.29/drivers/net/e1000/e1000_main.c linux-mips/drivers/net/e1000/e1000_main.c +--- linux-2.4.29/drivers/net/e1000/e1000_main.c 2005-01-19 15:09:56.000000000 +0100 ++++ linux-mips/drivers/net/e1000/e1000_main.c 2005-03-26 11:47:31.364504105 +0100 +@@ -34,6 +34,14 @@ + * - if_mii support and associated kcompat for older kernels + * - More errlogging support from Jon Mason <jonmason@us.ibm.com> + * - Fix TSO issues on PPC64 machines -- Jon Mason <jonmason@us.ibm.com> ++ * 5.7.1 12/16/04 ++ * - Resurrect 82547EI/GI related fix in e1000_intr to avoid deadlocks. This ++ * fix was removed as it caused system instability. The suspected cause of ++ * this is the called to e1000_irq_disable in e1000_intr. Inlined the ++ * required piece of e1000_irq_disable into e1000_intr. ++ * 5.7.0 12/10/04 ++ * - include fix to the condition that determines when to quit NAPI - Robert Olsson ++ * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down + * 5.6.5 11/01/04 + * - Enabling NETIF_F_SG without checksum offload is illegal - + John Mason <jdmason@us.ibm.com> +@@ -41,8 +49,13 @@ + * - Remove redundant initialization - Jamal Hadi + * - Reset buffer_info->dma in tx resource cleanup logic + * 5.6.2 10/12/04 ++ * - Avoid filling tx_ring completely - shemminger@osdl.org ++ * - Replace schedule_timeout() with msleep()/msleep_interruptible() - ++ * nacc@us.ibm.com + * - Sparse cleanup - shemminger@osdl.org + * - Fix tx resource cleanup logic ++ * - LLTX support - ak@suse.de and hadi@cyberus.ca ++ * - {set, get}_wol is now symmetric for 82545EM adapters + */ + + char e1000_driver_name[] = "e1000"; +@@ -52,7 +65,7 @@ + #else + #define DRIVERNAPI "-NAPI" + #endif +-char e1000_driver_version[] = "5.6.10.1-k1"DRIVERNAPI; ++char e1000_driver_version[] = "5.7.6-k1"DRIVERNAPI; + char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; + + /* e1000_pci_tbl - PCI Device ID Table +@@ -76,6 +89,7 @@ + INTEL_E1000_ETHERNET_DEVICE(0x1011), + INTEL_E1000_ETHERNET_DEVICE(0x1012), + INTEL_E1000_ETHERNET_DEVICE(0x1013), ++ INTEL_E1000_ETHERNET_DEVICE(0x1014), + INTEL_E1000_ETHERNET_DEVICE(0x1015), + INTEL_E1000_ETHERNET_DEVICE(0x1016), + INTEL_E1000_ETHERNET_DEVICE(0x1017), +@@ -303,6 +317,9 @@ + mod_timer(&adapter->watchdog_timer, jiffies); + e1000_irq_enable(adapter); + ++#ifdef CONFIG_E1000_NAPI ++ netif_poll_enable(netdev); ++#endif + return 0; + } + +@@ -316,6 +333,10 @@ + del_timer_sync(&adapter->tx_fifo_stall_timer); + del_timer_sync(&adapter->watchdog_timer); + del_timer_sync(&adapter->phy_info_timer); ++ ++#ifdef CONFIG_E1000_NAPI ++ netif_poll_disable(netdev); ++#endif + adapter->link_speed = 0; + adapter->link_duplex = 0; + netif_carrier_off(netdev); +@@ -409,6 +430,7 @@ + int i; + int err; + uint16_t eeprom_data; ++ uint16_t eeprom_apme_mask = E1000_EEPROM_APME; + + if((err = pci_enable_device(pdev))) + return err; +@@ -505,9 +527,6 @@ + } + + #ifdef NETIF_F_TSO +- /* Disbaled for now until root-cause is found for +- * hangs reported against non-IA archs. TSO can be +- * enabled using ethtool -K eth<x> tso on */ + if((adapter->hw.mac_type >= e1000_82544) && + (adapter->hw.mac_type != e1000_82547)) + netdev->features |= NETIF_F_TSO; +@@ -576,6 +595,11 @@ + case e1000_82542_rev2_1: + case e1000_82543: + break; ++ case e1000_82544: ++ e1000_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); ++ eeprom_apme_mask = E1000_EEPROM_82544_APM; ++ break; + case e1000_82546: + case e1000_82546_rev_3: + if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) +@@ -590,7 +614,7 @@ + EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + break; + } +- if(eeprom_data & E1000_EEPROM_APME) ++ if(eeprom_data & eeprom_apme_mask) + adapter->wol |= E1000_WUFC_MAG; + + /* reset the hardware with the new settings */ +@@ -797,6 +821,31 @@ + } + + /** ++ * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary ++ * @adapter: address of board private structure ++ * @begin: address of beginning of memory ++ * @end: address of end of memory ++ **/ ++static inline boolean_t ++e1000_check_64k_bound(struct e1000_adapter *adapter, ++ void *start, unsigned long len) ++{ ++ unsigned long begin = (unsigned long) start; ++ unsigned long end = begin + len; ++ ++ /* first rev 82545 and 82546 need to not allow any memory ++ * write location to cross a 64k boundary due to errata 23 */ ++ if (adapter->hw.mac_type == e1000_82545 || ++ adapter->hw.mac_type == e1000_82546 ) { ++ ++ /* check buffer doesn't cross 64kB */ ++ return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE; ++ } ++ ++ return TRUE; ++} ++ ++/** + * e1000_setup_tx_resources - allocate Tx resources (Descriptors) + * @adapter: board private structure + * +@@ -826,11 +875,42 @@ + + txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); + if(!txdr->desc) { ++setup_tx_desc_die: + DPRINTK(PROBE, ERR, + "Unable to Allocate Memory for the Transmit descriptor ring\n"); + vfree(txdr->buffer_info); + return -ENOMEM; + } ++ ++ /* fix for errata 23, cant cross 64kB boundary */ ++ if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ void *olddesc = txdr->desc; ++ dma_addr_t olddma = txdr->dma; ++ DPRINTK(TX_ERR,ERR,"txdr align check failed: %u bytes at %p\n", ++ txdr->size, txdr->desc); ++ /* try again, without freeing the previous */ ++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); ++ /* failed allocation, critial failure */ ++ if(!txdr->desc) { ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ goto setup_tx_desc_die; ++ } ++ ++ if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, txdr->size, ++ txdr->desc, txdr->dma); ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to Allocate aligned Memory for the Transmit" ++ " descriptor ring\n"); ++ vfree(txdr->buffer_info); ++ return -ENOMEM; ++ } else { ++ /* free old, move on with the new one since its okay */ ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ } ++ } + memset(txdr->desc, 0, txdr->size); + + txdr->next_to_use = 0; +@@ -948,11 +1028,43 @@ + rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); + + if(!rxdr->desc) { ++setup_rx_desc_die: + DPRINTK(PROBE, ERR, +- "Unable to Allocate Memory for the Recieve descriptor ring\n"); ++ "Unble to Allocate Memory for the Recieve descriptor ring\n"); + vfree(rxdr->buffer_info); + return -ENOMEM; + } ++ ++ /* fix for errata 23, cant cross 64kB boundary */ ++ if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ void *olddesc = rxdr->desc; ++ dma_addr_t olddma = rxdr->dma; ++ DPRINTK(RX_ERR,ERR, ++ "rxdr align check failed: %u bytes at %p\n", ++ rxdr->size, rxdr->desc); ++ /* try again, without freeing the previous */ ++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ /* failed allocation, critial failure */ ++ if(!rxdr->desc) { ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ goto setup_rx_desc_die; ++ } ++ ++ if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, rxdr->size, ++ rxdr->desc, rxdr->dma); ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to Allocate aligned Memory for the" ++ " Receive descriptor ring\n"); ++ vfree(rxdr->buffer_info); ++ return -ENOMEM; ++ } else { ++ /* free old, move on with the new one since its okay */ ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ } ++ } + memset(rxdr->desc, 0, rxdr->size); + + rxdr->next_to_clean = 0; +@@ -1086,6 +1198,7 @@ + struct e1000_buffer *buffer_info) + { + struct pci_dev *pdev = adapter->pdev; ++ + if(buffer_info->dma) { + pci_unmap_page(pdev, + buffer_info->dma, +@@ -1114,6 +1227,11 @@ + + /* Free all the Tx ring sk_buffs */ + ++ if (likely(adapter->previous_buffer_info.skb != NULL)) { ++ e1000_unmap_and_free_tx_resource(adapter, ++ &adapter->previous_buffer_info); ++ } ++ + for(i = 0; i < tx_ring->count; i++) { + buffer_info = &tx_ring->buffer_info[i]; + e1000_unmap_and_free_tx_resource(adapter, buffer_info); +@@ -1415,7 +1533,6 @@ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + struct net_device *netdev = adapter->netdev; + struct e1000_desc_ring *txdr = &adapter->tx_ring; +- unsigned int i; + uint32_t link; + + e1000_check_for_link(&adapter->hw); +@@ -1495,12 +1612,8 @@ + /* Cause software interrupt to ensure rx ring is cleaned */ + E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); + +- /* Early detection of hung controller */ +- i = txdr->next_to_clean; +- if(txdr->buffer_info[i].dma && +- time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) && +- !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) +- netif_stop_queue(netdev); ++ /* Force detection of hung controller every watchdog period*/ ++ adapter->detect_tx_hung = TRUE; + + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); +@@ -2132,10 +2245,28 @@ + __netif_rx_schedule(netdev); + } + #else ++ /* Writing IMC and IMS is needed for 82547. ++ Due to Hub Link bus being occupied, an interrupt ++ de-assertion message is not able to be sent. ++ When an interrupt assertion message is generated later, ++ two messages are re-ordered and sent out. ++ That causes APIC to think 82547 is in de-assertion ++ state, while 82547 is in assertion state, resulting ++ in dead lock. Writing IMC forces 82547 into ++ de-assertion state. ++ */ ++ if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){ ++ atomic_inc(&adapter->irq_sem); ++ E1000_WRITE_REG(&adapter->hw, IMC, ~0); ++ } ++ + for(i = 0; i < E1000_MAX_INTR; i++) + if(unlikely(!e1000_clean_rx_irq(adapter) & + !e1000_clean_tx_irq(adapter))) + break; ++ ++ if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) ++ e1000_irq_enable(adapter); + #endif + + return IRQ_HANDLED; +@@ -2155,24 +2286,21 @@ + int tx_cleaned; + int work_done = 0; + +- if (!netif_carrier_ok(netdev)) +- goto quit_polling; +- + tx_cleaned = e1000_clean_tx_irq(adapter); + e1000_clean_rx_irq(adapter, &work_done, work_to_do); + + *budget -= work_done; + netdev->quota -= work_done; + +- /* if no Rx and Tx cleanup work was done, exit the polling mode */ +- if(!tx_cleaned || (work_done < work_to_do) || ++ /* if no Tx and not enough Rx work done, exit the polling mode */ ++ if((!tx_cleaned && (work_done < work_to_do)) || + !netif_running(netdev)) { +-quit_polling: netif_rx_complete(netdev); ++ netif_rx_complete(netdev); + e1000_irq_enable(adapter); + return 0; + } + +- return (work_done >= work_to_do); ++ return 1; + } + + #endif +@@ -2196,11 +2324,34 @@ + eop_desc = E1000_TX_DESC(*tx_ring, eop); + + while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { ++ /* pre-mature writeback of Tx descriptors */ ++ /* clear (free buffers and unmap pci_mapping) */ ++ /* previous_buffer_info */ ++ if (likely(adapter->previous_buffer_info.skb != NULL)) { ++ e1000_unmap_and_free_tx_resource(adapter, ++ &adapter->previous_buffer_info); ++ } ++ + for(cleaned = FALSE; !cleaned; ) { + tx_desc = E1000_TX_DESC(*tx_ring, i); + buffer_info = &tx_ring->buffer_info[i]; ++ cleaned = (i == eop); ++ ++ /* pre-mature writeback of Tx descriptors */ ++ /* save the cleaning of the this for the */ ++ /* next iteration */ ++ if (cleaned) { ++ memcpy(&adapter->previous_buffer_info, ++ buffer_info, ++ sizeof(struct e1000_buffer)); ++ memset(buffer_info, ++ 0, ++ sizeof(struct e1000_buffer)); ++ } else { ++ e1000_unmap_and_free_tx_resource(adapter, ++ buffer_info); ++ } + +- e1000_unmap_and_free_tx_resource(adapter, buffer_info); + tx_desc->buffer_addr = 0; + tx_desc->lower.data = 0; + tx_desc->upper.data = 0; +@@ -2222,6 +2373,16 @@ + netif_wake_queue(netdev); + + spin_unlock(&adapter->tx_lock); ++ ++ if(adapter->detect_tx_hung) { ++ /* detect a transmit hang in hardware, this serializes the ++ * check with the clearing of time_stamp and movement of i */ ++ adapter->detect_tx_hung = FALSE; ++ if(tx_ring->buffer_info[i].dma && ++ time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) && ++ !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) ++ netif_stop_queue(netdev); ++ } + + return cleaned; + } +@@ -2389,20 +2550,43 @@ + struct e1000_buffer *buffer_info; + struct sk_buff *skb; + int reserve_len = 2; +- unsigned int i; ++ unsigned int i, bufsz; + + i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; + + while(!buffer_info->skb) { ++ bufsz = adapter->rx_buffer_len + reserve_len; + +- skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len); +- ++ skb = dev_alloc_skb(bufsz); + if(unlikely(!skb)) { + /* Better luck next round */ + break; + } + ++ /* fix for errata 23, cant cross 64kB boundary */ ++ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { ++ struct sk_buff *oldskb = skb; ++ DPRINTK(RX_ERR,ERR, ++ "skb align check failed: %u bytes at %p\n", ++ bufsz, skb->data); ++ /* try again, without freeing the previous */ ++ skb = dev_alloc_skb(bufsz); ++ if (!skb) { ++ dev_kfree_skb(oldskb); ++ break; ++ } ++ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { ++ /* give up */ ++ dev_kfree_skb(skb); ++ dev_kfree_skb(oldskb); ++ break; /* while !buffer_info->skb */ ++ } else { ++ /* move on with the new one */ ++ dev_kfree_skb(oldskb); ++ } ++ } ++ + /* Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed +@@ -2418,6 +2602,25 @@ + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + ++ /* fix for errata 23, cant cross 64kB boundary */ ++ if(!e1000_check_64k_bound(adapter, ++ (void *)(unsigned long)buffer_info->dma, ++ adapter->rx_buffer_len)) { ++ DPRINTK(RX_ERR,ERR, ++ "dma align check failed: %u bytes at %ld\n", ++ adapter->rx_buffer_len, (unsigned long)buffer_info->dma); ++ ++ dev_kfree_skb(skb); ++ buffer_info->skb = NULL; ++ ++ pci_unmap_single(pdev, ++ buffer_info->dma, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); ++ ++ break; /* while !buffer_info->skb */ ++ } ++ + rx_desc = E1000_RX_DESC(*rx_ring, i); + rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + diff -Nur linux-2.4.29/drivers/net/hamradio/hdlcdrv.c linux-mips/drivers/net/hamradio/hdlcdrv.c --- linux-2.4.29/drivers/net/hamradio/hdlcdrv.c 2002-02-25 20:37:59.000000000 +0100 +++ linux-mips/drivers/net/hamradio/hdlcdrv.c 2004-05-04 14:04:27.000000000 +0200 @@ -16206,7 +20613,7 @@ diff -Nur linux-2.4.29/drivers/net/hamradio/hdlcdrv.c linux-mips/drivers/net/ham if (s->skb) diff -Nur linux-2.4.29/drivers/net/irda/au1k_ir.c linux-mips/drivers/net/irda/au1k_ir.c --- linux-2.4.29/drivers/net/irda/au1k_ir.c 2004-02-18 14:36:31.000000000 +0100 -+++ linux-mips/drivers/net/irda/au1k_ir.c 2005-02-12 04:06:52.000000000 +0100 ++++ linux-mips/drivers/net/irda/au1k_ir.c 2005-03-26 11:47:31.367503613 +0100 @@ -81,10 +81,6 @@ #define RUN_AT(x) (jiffies + (x)) @@ -16218,6 +20625,1569 @@ diff -Nur linux-2.4.29/drivers/net/irda/au1k_ir.c linux-mips/drivers/net/irda/au static spinlock_t ir_lock = SPIN_LOCK_UNLOCKED; /* +diff -Nur linux-2.4.29/drivers/net/sk98lin/skvpd.c linux-mips/drivers/net/sk98lin/skvpd.c +--- linux-2.4.29/drivers/net/sk98lin/skvpd.c 2004-04-14 15:05:30.000000000 +0200 ++++ linux-mips/drivers/net/sk98lin/skvpd.c 2005-03-26 11:47:31.369503284 +0100 +@@ -466,6 +466,15 @@ + + pAC->vpd.vpd_size = vpd_size; + ++ /* Asus K8V Se Deluxe bugfix. Correct VPD content */ ++ /* MBo April 2004 */ ++ if( ((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) && ++ ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) && ++ ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45) ) { ++ printk(KERN_INFO "sk98lin : humm... Asus mainboard with buggy VPD ? correcting data.\n"); ++ (unsigned char)pAC->vpd.vpd_buf[0x40] = 0x38; ++ } ++ + /* find the end tag of the RO area */ + if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, +diff -Nur linux-2.4.29/drivers/net/tg3.c linux-mips/drivers/net/tg3.c +--- linux-2.4.29/drivers/net/tg3.c 2005-01-19 15:09:56.000000000 +0100 ++++ linux-mips/drivers/net/tg3.c 2005-03-26 11:47:30.480649166 +0100 +@@ -59,8 +59,8 @@ + + #define DRV_MODULE_NAME "tg3" + #define PFX DRV_MODULE_NAME ": " +-#define DRV_MODULE_VERSION "3.15" +-#define DRV_MODULE_RELDATE "January 6, 2005" ++#define DRV_MODULE_VERSION "3.24" ++#define DRV_MODULE_RELDATE "March 4, 2005" + + #define TG3_DEF_MAC_MODE 0 + #define TG3_DEF_RX_MODE 0 +@@ -575,9 +575,10 @@ + if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) + return; + +- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); +- tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); +- tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); ++ if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) && ++ !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val)) ++ tg3_writephy(tp, MII_TG3_AUX_CTRL, ++ (val | (1 << 15) | (1 << 4))); + } + + static int tg3_bmcr_reset(struct tg3 *tp) +@@ -618,9 +619,10 @@ + while (limit--) { + u32 tmp32; + +- tg3_readphy(tp, 0x16, &tmp32); +- if ((tmp32 & 0x1000) == 0) +- break; ++ if (!tg3_readphy(tp, 0x16, &tmp32)) { ++ if ((tmp32 & 0x1000) == 0) ++ break; ++ } + } + if (limit <= 0) + return -EBUSY; +@@ -672,9 +674,9 @@ + for (i = 0; i < 6; i += 2) { + u32 low, high; + +- tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low); +- tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high); +- if (tg3_wait_macro_done(tp)) { ++ if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) || ++ tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) || ++ tg3_wait_macro_done(tp)) { + *resetp = 1; + return -EBUSY; + } +@@ -730,7 +732,9 @@ + } + + /* Disable transmitter and interrupt. */ +- tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); ++ if (tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) ++ continue; ++ + reg32 |= 0x3000; + tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); + +@@ -739,7 +743,9 @@ + BMCR_FULLDPLX | TG3_BMCR_SPEED1000); + + /* Set to master mode. */ +- tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig); ++ if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig)) ++ continue; ++ + tg3_writephy(tp, MII_TG3_CTRL, + (MII_TG3_CTRL_AS_MASTER | + MII_TG3_CTRL_ENABLE_AS_MASTER)); +@@ -777,9 +783,11 @@ + + tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); + +- tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); +- reg32 &= ~0x3000; +- tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); ++ if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32)) { ++ reg32 &= ~0x3000; ++ tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); ++ } else if (!err) ++ err = -EBUSY; + + return err; + } +@@ -843,9 +851,9 @@ + u32 phy_reg; + + /* Set bit 14 with read-modify-write to preserve other bits */ +- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007); +- tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg); +- tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); ++ if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) && ++ !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg)) ++ tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); + } + tg3_phy_set_wirespeed(tp); + return 0; +@@ -877,7 +885,7 @@ + GRC_LCLCTRL_GPIO_OUTPUT1)); + udelay(100); + } else { +- int no_gpio2; ++ u32 no_gpio2; + u32 grc_local_ctrl; + + if (tp_peer != tp && +@@ -885,8 +893,8 @@ + return; + + /* On 5753 and variants, GPIO2 cannot be used. */ +- no_gpio2 = (tp->nic_sram_data_cfg & +- NIC_SRAM_DATA_CFG_NO_GPIO2) != 0; ++ no_gpio2 = tp->nic_sram_data_cfg & ++ NIC_SRAM_DATA_CFG_NO_GPIO2; + + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | +@@ -898,29 +906,17 @@ + GRC_LCLCTRL_GPIO_OUTPUT2); + } + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | +- grc_local_ctrl); ++ grc_local_ctrl); + udelay(100); + +- grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | +- GRC_LCLCTRL_GPIO_OE1 | +- GRC_LCLCTRL_GPIO_OE2 | +- GRC_LCLCTRL_GPIO_OUTPUT0 | +- GRC_LCLCTRL_GPIO_OUTPUT1 | +- GRC_LCLCTRL_GPIO_OUTPUT2; +- if (no_gpio2) { +- grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | +- GRC_LCLCTRL_GPIO_OUTPUT2); +- } ++ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0; ++ + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | +- grc_local_ctrl); ++ grc_local_ctrl); + udelay(100); + +- grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | +- GRC_LCLCTRL_GPIO_OE1 | +- GRC_LCLCTRL_GPIO_OE2 | +- GRC_LCLCTRL_GPIO_OUTPUT0 | +- GRC_LCLCTRL_GPIO_OUTPUT1; + if (!no_gpio2) { ++ grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2; + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + grc_local_ctrl); + udelay(100); +@@ -1240,7 +1236,7 @@ + }; + } + +-static int tg3_phy_copper_begin(struct tg3 *tp) ++static void tg3_phy_copper_begin(struct tg3 *tp) + { + u32 new_adv; + int i; +@@ -1355,15 +1351,16 @@ + if (tp->link_config.duplex == DUPLEX_FULL) + bmcr |= BMCR_FULLDPLX; + +- tg3_readphy(tp, MII_BMCR, &orig_bmcr); +- if (bmcr != orig_bmcr) { ++ if (!tg3_readphy(tp, MII_BMCR, &orig_bmcr) && ++ (bmcr != orig_bmcr)) { + tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK); + for (i = 0; i < 1500; i++) { + u32 tmp; + + udelay(10); +- tg3_readphy(tp, MII_BMSR, &tmp); +- tg3_readphy(tp, MII_BMSR, &tmp); ++ if (tg3_readphy(tp, MII_BMSR, &tmp) || ++ tg3_readphy(tp, MII_BMSR, &tmp)) ++ continue; + if (!(tmp & BMSR_LSTATUS)) { + udelay(40); + break; +@@ -1376,8 +1373,6 @@ + tg3_writephy(tp, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); + } +- +- return 0; + } + + static int tg3_init_5401phy_dsp(struct tg3 *tp) +@@ -1412,7 +1407,9 @@ + { + u32 adv_reg, all_mask; + +- tg3_readphy(tp, MII_ADVERTISE, &adv_reg); ++ if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg)) ++ return 0; ++ + all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL); + if ((adv_reg & all_mask) != all_mask) +@@ -1420,7 +1417,9 @@ + if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { + u32 tg3_ctrl; + +- tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl); ++ if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl)) ++ return 0; ++ + all_mask = (MII_TG3_CTRL_ADV_1000_HALF | + MII_TG3_CTRL_ADV_1000_FULL); + if ((tg3_ctrl & all_mask) != all_mask) +@@ -1460,8 +1459,8 @@ + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && + netif_carrier_ok(tp->dev)) { + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- if (!(bmsr & BMSR_LSTATUS)) ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ !(bmsr & BMSR_LSTATUS)) + force_reset = 1; + } + if (force_reset) +@@ -1469,9 +1468,8 @@ + + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- +- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) ++ if (tg3_readphy(tp, MII_BMSR, &bmsr) || ++ !(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) + bmsr = 0; + + if (!(bmsr & BMSR_LSTATUS)) { +@@ -1482,8 +1480,8 @@ + tg3_readphy(tp, MII_BMSR, &bmsr); + for (i = 0; i < 1000; i++) { + udelay(10); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- if (bmsr & BMSR_LSTATUS) { ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ (bmsr & BMSR_LSTATUS)) { + udelay(40); + break; + } +@@ -1545,8 +1543,8 @@ + bmsr = 0; + for (i = 0; i < 100; i++) { + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- if (bmsr & BMSR_LSTATUS) ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ (bmsr & BMSR_LSTATUS)) + break; + udelay(40); + } +@@ -1557,8 +1555,8 @@ + tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); + for (i = 0; i < 2000; i++) { + udelay(10); +- tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); +- if (aux_stat) ++ if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) && ++ aux_stat) + break; + } + +@@ -1569,7 +1567,8 @@ + bmcr = 0; + for (i = 0; i < 200; i++) { + tg3_readphy(tp, MII_BMCR, &bmcr); +- tg3_readphy(tp, MII_BMCR, &bmcr); ++ if (tg3_readphy(tp, MII_BMCR, &bmcr)) ++ continue; + if (bmcr && bmcr != 0x7fff) + break; + udelay(10); +@@ -1606,10 +1605,13 @@ + (tp->link_config.autoneg == AUTONEG_ENABLE)) { + u32 local_adv, remote_adv; + +- tg3_readphy(tp, MII_ADVERTISE, &local_adv); ++ if (tg3_readphy(tp, MII_ADVERTISE, &local_adv)) ++ local_adv = 0; + local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + +- tg3_readphy(tp, MII_LPA, &remote_adv); ++ if (tg3_readphy(tp, MII_LPA, &remote_adv)) ++ remote_adv = 0; ++ + remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); + + /* If we are not advertising full pause capability, +@@ -1628,8 +1630,8 @@ + tg3_phy_copper_begin(tp); + + tg3_readphy(tp, MII_BMSR, &tmp); +- tg3_readphy(tp, MII_BMSR, &tmp); +- if (tmp & BMSR_LSTATUS) ++ if (!tg3_readphy(tp, MII_BMSR, &tmp) && ++ (tmp & BMSR_LSTATUS)) + current_link_up = 1; + } + +@@ -2130,8 +2132,9 @@ + if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) + port_a = 0; + +- serdes_cfg = tr32(MAC_SERDES_CFG) & +- ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20)); ++ /* preserve bits 0-11,13,14 for signal pre-emphasis */ ++ /* preserve bits 20-23 for voltage regulator */ ++ serdes_cfg = tr32(MAC_SERDES_CFG) & 0x00f06fff; + } + + sg_dig_ctrl = tr32(SG_DIG_CTRL); +@@ -2142,9 +2145,9 @@ + u32 val = serdes_cfg; + + if (port_a) +- val |= 0xc010880; ++ val |= 0xc010000; + else +- val |= 0x4010880; ++ val |= 0x4010000; + tw32_f(MAC_SERDES_CFG, val); + } + tw32_f(SG_DIG_CTRL, 0x01388400); +@@ -2167,7 +2170,7 @@ + + if (sg_dig_ctrl != expected_sg_dig_ctrl) { + if (workaround) +- tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880); ++ tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000); + tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); + udelay(5); + tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); +@@ -2208,9 +2211,9 @@ + u32 val = serdes_cfg; + + if (port_a) +- val |= 0xc010880; ++ val |= 0xc010000; + else +- val |= 0x4010880; ++ val |= 0x4010000; + + tw32_f(MAC_SERDES_CFG, val); + } +@@ -2218,8 +2221,12 @@ + tw32_f(SG_DIG_CTRL, 0x01388400); + udelay(40); + ++ /* Link parallel detection - link is up */ ++ /* only if we have PCS_SYNC and not */ ++ /* receiving config code words */ + mac_status = tr32(MAC_STATUS); +- if (mac_status & MAC_STATUS_PCS_SYNCED) { ++ if ((mac_status & MAC_STATUS_PCS_SYNCED) && ++ !(mac_status & MAC_STATUS_RCVD_CFG)) { + tg3_setup_flow_control(tp, 0, 0); + current_link_up = 1; + } +@@ -2690,7 +2697,11 @@ + + len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ + +- if (len > RX_COPY_THRESHOLD) { ++ if (len > RX_COPY_THRESHOLD ++ && tp->rx_offset == 2 ++ /* rx_offset != 2 iff this is a 5701 card running ++ * in PCI-X mode [see tg3_get_invariants()] */ ++ ) { + int skb_size; + + skb_size = tg3_alloc_rx_skb(tp, opaque_key, +@@ -3085,11 +3096,19 @@ + + skb->nh.iph->check = 0; + skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); +- skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, +- skb->nh.iph->daddr, +- 0, IPPROTO_TCP, 0); ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { ++ skb->h.th->check = 0; ++ base_flags &= ~TXD_FLAG_TCPUDP_CSUM; ++ } ++ else { ++ skb->h.th->check = ++ ~csum_tcpudp_magic(skb->nh.iph->saddr, ++ skb->nh.iph->daddr, ++ 0, IPPROTO_TCP, 0); ++ } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { ++ if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) || ++ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) { + if (tcp_opt_len || skb->nh.iph->ihl > 5) { + int tsflags; + +@@ -3156,7 +3175,7 @@ + would_hit_hwbug = entry + 1; + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + tg3_set_txd(tp, entry, mapping, len, + base_flags, (i == last)|(mss << 1)); + else +@@ -3655,8 +3674,9 @@ + /* tp->lock is held. */ + static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) + { +- tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, +- NIC_SRAM_FIRMWARE_MBOX_MAGIC1); ++ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) ++ tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, ++ NIC_SRAM_FIRMWARE_MBOX_MAGIC1); + + if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) { + switch (kind) { +@@ -3860,19 +3880,20 @@ + tw32_f(MAC_MODE, 0); + udelay(40); + +- /* Wait for firmware initialization to complete. */ +- for (i = 0; i < 100000; i++) { +- tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); +- if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) +- break; +- udelay(10); +- } +- if (i >= 100000 && +- !(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { +- printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " +- "firmware will not restart magic=%08x\n", +- tp->dev->name, val); +- return -ENODEV; ++ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { ++ /* Wait for firmware initialization to complete. */ ++ for (i = 0; i < 100000; i++) { ++ tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); ++ if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) ++ break; ++ udelay(10); ++ } ++ if (i >= 100000) { ++ printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " ++ "firmware will not restart magic=%08x\n", ++ tp->dev->name, val); ++ return -ENODEV; ++ } + } + + if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && +@@ -4747,7 +4768,7 @@ + unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; + int err, i; + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + return 0; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { +@@ -4831,9 +4852,8 @@ + tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); + } + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || ++ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { + for (i = 0; i < 12; i++) { + tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high); + tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low); +@@ -4879,7 +4899,8 @@ + (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS), + maxlen_flags); + +- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) && ++ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) + tg3_write_mem(tp, + (bdinfo_addr + TG3_BDINFO_NIC_ADDR), + nic_addr); +@@ -5181,7 +5202,7 @@ + } + + #if TG3_TSO_SUPPORT != 0 +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + rdmac_mode |= (1 << 27); + #endif + +@@ -5331,7 +5352,7 @@ + tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ); + tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); + #if TG3_TSO_SUPPORT != 0 +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) + tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8); + #endif + tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE); +@@ -5381,8 +5402,10 @@ + udelay(10); + + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) && ++ !(tp->tg3_flags2 & TG3_FLG2_SERDES_PREEMPHASIS)) { + /* Set drive transmission level to 1.2V */ ++ /* only if the signal pre-emphasis bit is not set */ + val = tr32(MAC_SERDES_CFG); + val &= 0xfffff000; + val |= 0x880; +@@ -5411,9 +5434,10 @@ + u32 tmp; + + /* Clear CRC stats. */ +- tg3_readphy(tp, 0x1e, &tmp); +- tg3_writephy(tp, 0x1e, tmp | 0x8000); +- tg3_readphy(tp, 0x14, &tmp); ++ if (!tg3_readphy(tp, 0x1e, &tmp)) { ++ tg3_writephy(tp, 0x1e, tmp | 0x8000); ++ tg3_readphy(tp, 0x14, &tmp); ++ } + } + + __tg3_set_rx_mode(tp->dev); +@@ -6003,9 +6027,11 @@ + u32 val; + + spin_lock_irqsave(&tp->lock, flags); +- tg3_readphy(tp, 0x1e, &val); +- tg3_writephy(tp, 0x1e, val | 0x8000); +- tg3_readphy(tp, 0x14, &val); ++ if (!tg3_readphy(tp, 0x1e, &val)) { ++ tg3_writephy(tp, 0x1e, val | 0x8000); ++ tg3_readphy(tp, 0x14, &val); ++ } else ++ val = 0; + spin_unlock_irqrestore(&tp->lock, flags); + + tp->phy_crc_errors += val; +@@ -6349,11 +6375,13 @@ + + static int tg3_get_eeprom_len(struct net_device *dev) + { +- return EEPROM_CHIP_SIZE; ++ struct tg3 *tp = netdev_priv(dev); ++ ++ return tp->nvram_size; + } + +-static int tg3_nvram_read_using_eeprom(struct tg3 *tp, +- u32 offset, u32 *val); ++static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val); ++ + static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) + { + struct tg3 *tp = dev->priv; +@@ -6365,10 +6393,7 @@ + len = eeprom->len; + eeprom->len = 0; + +- ret = tg3_nvram_read_using_eeprom(tp, 0, &eeprom->magic); +- if (ret) +- return ret; +- eeprom->magic = swab32(eeprom->magic); ++ eeprom->magic = TG3_EEPROM_MAGIC; + + if (offset & 3) { + /* adjustments to start on required 4 byte boundary */ +@@ -6378,9 +6403,10 @@ + /* i.e. offset=1 len=2 */ + b_count = len; + } +- ret = tg3_nvram_read_using_eeprom(tp, offset-b_offset, &val); ++ ret = tg3_nvram_read(tp, offset-b_offset, &val); + if (ret) + return ret; ++ val = cpu_to_le32(val); + memcpy(data, ((char*)&val) + b_offset, b_count); + len -= b_count; + offset += b_count; +@@ -6390,12 +6416,13 @@ + /* read bytes upto the last 4 byte boundary */ + pd = &data[eeprom->len]; + for (i = 0; i < (len - (len & 3)); i += 4) { +- ret = tg3_nvram_read_using_eeprom(tp, offset + i, +- (u32*)(pd + i)); ++ ret = tg3_nvram_read(tp, offset + i, &val); + if (ret) { + eeprom->len += i; + return ret; + } ++ val = cpu_to_le32(val); ++ memcpy(pd + i, &val, 4); + } + eeprom->len += i; + +@@ -6404,15 +6431,72 @@ + pd = &data[eeprom->len]; + b_count = len & 3; + b_offset = offset + len - b_count; +- ret = tg3_nvram_read_using_eeprom(tp, b_offset, &val); ++ ret = tg3_nvram_read(tp, b_offset, &val); + if (ret) + return ret; ++ val = cpu_to_le32(val); + memcpy(pd, ((char*)&val), b_count); + eeprom->len += b_count; + } + return 0; + } + ++static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); ++ ++static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) ++{ ++ struct tg3 *tp = netdev_priv(dev); ++ int ret; ++ u32 offset, len, b_offset, odd_len, start, end; ++ u8 *buf; ++ ++ if (eeprom->magic != TG3_EEPROM_MAGIC) ++ return -EINVAL; ++ ++ offset = eeprom->offset; ++ len = eeprom->len; ++ ++ if ((b_offset = (offset & 3))) { ++ /* adjustments to start on required 4 byte boundary */ ++ ret = tg3_nvram_read(tp, offset-b_offset, &start); ++ if (ret) ++ return ret; ++ start = cpu_to_le32(start); ++ len += b_offset; ++ offset &= ~3; ++ } ++ ++ odd_len = 0; ++ if ((len & 3) && ((len > 4) || (b_offset == 0))) { ++ /* adjustments to end on required 4 byte boundary */ ++ odd_len = 1; ++ len = (len + 3) & ~3; ++ ret = tg3_nvram_read(tp, offset+len-4, &end); ++ if (ret) ++ return ret; ++ end = cpu_to_le32(end); ++ } ++ ++ buf = data; ++ if (b_offset || odd_len) { ++ buf = kmalloc(len, GFP_KERNEL); ++ if (buf == 0) ++ return -ENOMEM; ++ if (b_offset) ++ memcpy(buf, &start, 4); ++ if (odd_len) ++ memcpy(buf+len-4, &end, 4); ++ memcpy(buf + b_offset, data, eeprom->len); ++ } ++ ++ ret = tg3_nvram_write_block(tp, offset, len, buf); ++ ++ if (buf != data) ++ kfree(buf); ++ ++ return ret; ++} ++ + static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct tg3 *tp = netdev_priv(dev); +@@ -6561,10 +6645,10 @@ + int r; + + spin_lock_irq(&tp->lock); +- tg3_readphy(tp, MII_BMCR, &bmcr); +- tg3_readphy(tp, MII_BMCR, &bmcr); + r = -EINVAL; +- if (bmcr & BMCR_ANENABLE) { ++ tg3_readphy(tp, MII_BMCR, &bmcr); ++ if (!tg3_readphy(tp, MII_BMCR, &bmcr) && ++ (bmcr & BMCR_ANENABLE)) { + tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); + r = 0; + } +@@ -6812,6 +6896,7 @@ + .get_link = ethtool_op_get_link, + .get_eeprom_len = tg3_get_eeprom_len, + .get_eeprom = tg3_get_eeprom, ++ .set_eeprom = tg3_set_eeprom, + .get_ringparam = tg3_get_ringparam, + .set_ringparam = tg3_set_ringparam, + .get_pauseparam = tg3_get_pauseparam, +@@ -6831,6 +6916,103 @@ + .get_ethtool_stats = tg3_get_ethtool_stats, + }; + ++static void __devinit tg3_get_eeprom_size(struct tg3 *tp) ++{ ++ u32 cursize, val; ++ ++ tp->nvram_size = EEPROM_CHIP_SIZE; ++ ++ if (tg3_nvram_read(tp, 0, &val) != 0) ++ return; ++ ++ if (swab32(val) != TG3_EEPROM_MAGIC) ++ return; ++ ++ /* ++ * Size the chip by reading offsets at increasing powers of two. ++ * When we encounter our validation signature, we know the addressing ++ * has wrapped around, and thus have our chip size. ++ */ ++ cursize = 0x800; ++ ++ while (cursize < tp->nvram_size) { ++ if (tg3_nvram_read(tp, cursize, &val) != 0) ++ return; ++ ++ if (swab32(val) == TG3_EEPROM_MAGIC) ++ break; ++ ++ cursize <<= 1; ++ } ++ ++ tp->nvram_size = cursize; ++} ++ ++static void __devinit tg3_get_nvram_size(struct tg3 *tp) ++{ ++ u32 val; ++ ++ if (tg3_nvram_read(tp, 0xf0, &val) == 0) { ++ if (val != 0) { ++ tp->nvram_size = (val >> 16) * 1024; ++ return; ++ } ++ } ++ tp->nvram_size = 0x20000; ++} ++ ++static void __devinit tg3_get_nvram_info(struct tg3 *tp) ++{ ++ u32 nvcfg1; ++ ++ nvcfg1 = tr32(NVRAM_CFG1); ++ if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { ++ tp->tg3_flags2 |= TG3_FLG2_FLASH; ++ } ++ else { ++ nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; ++ tw32(NVRAM_CFG1, nvcfg1); ++ } ++ ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) { ++ case FLASH_VENDOR_ATMEL_FLASH_BUFFERED: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ break; ++ case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE; ++ break; ++ case FLASH_VENDOR_ATMEL_EEPROM: ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ break; ++ case FLASH_VENDOR_ST: ++ tp->nvram_jedecnum = JEDEC_ST; ++ tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ break; ++ case FLASH_VENDOR_SAIFUN: ++ tp->nvram_jedecnum = JEDEC_SAIFUN; ++ tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE; ++ break; ++ case FLASH_VENDOR_SST_SMALL: ++ case FLASH_VENDOR_SST_LARGE: ++ tp->nvram_jedecnum = JEDEC_SST; ++ tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE; ++ break; ++ } ++ } ++ else { ++ tp->nvram_jedecnum = JEDEC_ATMEL; ++ tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE; ++ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; ++ } ++} ++ + /* Chips other than 5700/5701 use the NVRAM for fetching info. */ + static void __devinit tg3_nvram_init(struct tg3 *tp) + { +@@ -6855,32 +7037,27 @@ + + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { +- u32 nvcfg1; ++ tp->tg3_flags |= TG3_FLAG_NVRAM; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { + u32 nvaccess = tr32(NVRAM_ACCESS); + +- tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); ++ tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); + } + +- nvcfg1 = tr32(NVRAM_CFG1); +- +- tp->tg3_flags |= TG3_FLAG_NVRAM; +- if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { +- if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE) +- tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; +- } else { +- nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; +- tw32(NVRAM_CFG1, nvcfg1); +- } ++ tg3_get_nvram_info(tp); ++ tg3_get_nvram_size(tp); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { + u32 nvaccess = tr32(NVRAM_ACCESS); + +- tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); ++ tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); + } ++ + } else { + tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED); ++ ++ tg3_get_eeprom_size(tp); + } + } + +@@ -6918,11 +7095,30 @@ + return 0; + } + +-static int __devinit tg3_nvram_read(struct tg3 *tp, +- u32 offset, u32 *val) ++#define NVRAM_CMD_TIMEOUT 10000 ++ ++static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd) + { + int i; + ++ tw32(NVRAM_CMD, nvram_cmd); ++ for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) { ++ udelay(10); ++ if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) { ++ udelay(10); ++ break; ++ } ++ } ++ if (i == NVRAM_CMD_TIMEOUT) { ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) ++{ ++ int ret; ++ + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { + printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n"); + return -EINVAL; +@@ -6931,10 +7127,14 @@ + if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) + return tg3_nvram_read_using_eeprom(tp, offset, val); + +- if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) +- offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) << +- NVRAM_BUFFERED_PAGE_POS) + +- (offset % NVRAM_BUFFERED_PAGE_SIZE); ++ if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) && ++ (tp->tg3_flags2 & TG3_FLG2_FLASH) && ++ (tp->nvram_jedecnum == JEDEC_ATMEL)) { ++ ++ offset = ((offset / tp->nvram_pagesize) << ++ ATMEL_AT45DB0X1B_PAGE_POS) + ++ (offset % tp->nvram_pagesize); ++ } + + if (offset > NVRAM_ADDR_MSK) + return -EINVAL; +@@ -6948,19 +7148,11 @@ + } + + tw32(NVRAM_ADDR, offset); +- tw32(NVRAM_CMD, +- NVRAM_CMD_RD | NVRAM_CMD_GO | +- NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); ++ ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO | ++ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); + +- /* Wait for done bit to clear. */ +- for (i = 0; i < 1000; i++) { +- udelay(10); +- if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) { +- udelay(10); +- *val = swab32(tr32(NVRAM_RDDATA)); +- break; +- } +- } ++ if (ret == 0) ++ *val = swab32(tr32(NVRAM_RDDATA)); + + tg3_nvram_unlock(tp); + +@@ -6970,10 +7162,268 @@ + tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); + } + +- if (i >= 1000) +- return -EBUSY; ++ return ret; ++} + +- return 0; ++static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, ++ u32 offset, u32 len, u8 *buf) ++{ ++ int i, j, rc = 0; ++ u32 val; ++ ++ for (i = 0; i < len; i += 4) { ++ u32 addr, data; ++ ++ addr = offset + i; ++ ++ memcpy(&data, buf + i, 4); ++ ++ tw32(GRC_EEPROM_DATA, cpu_to_le32(data)); ++ ++ val = tr32(GRC_EEPROM_ADDR); ++ tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE); ++ ++ val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK | ++ EEPROM_ADDR_READ); ++ tw32(GRC_EEPROM_ADDR, val | ++ (0 << EEPROM_ADDR_DEVID_SHIFT) | ++ (addr & EEPROM_ADDR_ADDR_MASK) | ++ EEPROM_ADDR_START | ++ EEPROM_ADDR_WRITE); ++ ++ for (j = 0; j < 10000; j++) { ++ val = tr32(GRC_EEPROM_ADDR); ++ ++ if (val & EEPROM_ADDR_COMPLETE) ++ break; ++ udelay(100); ++ } ++ if (!(val & EEPROM_ADDR_COMPLETE)) { ++ rc = -EBUSY; ++ break; ++ } ++ } ++ ++ return rc; ++} ++ ++/* offset and length are dword aligned */ ++static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, ++ u8 *buf) ++{ ++ int ret = 0; ++ u32 pagesize = tp->nvram_pagesize; ++ u32 pagemask = pagesize - 1; ++ u32 nvram_cmd; ++ u8 *tmp; ++ ++ tmp = kmalloc(pagesize, GFP_KERNEL); ++ if (tmp == NULL) ++ return -ENOMEM; ++ ++ while (len) { ++ int j; ++ u32 phy_addr, page_off, size, nvaccess; ++ ++ phy_addr = offset & ~pagemask; ++ ++ for (j = 0; j < pagesize; j += 4) { ++ if ((ret = tg3_nvram_read(tp, phy_addr + j, ++ (u32 *) (tmp + j)))) ++ break; ++ } ++ if (ret) ++ break; ++ ++ page_off = offset & pagemask; ++ size = pagesize; ++ if (len < size) ++ size = len; ++ ++ len -= size; ++ ++ memcpy(tmp + page_off, buf, size); ++ ++ offset = offset + (pagesize - page_off); ++ ++ nvaccess = tr32(NVRAM_ACCESS); ++ tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); ++ ++ /* ++ * Before we can erase the flash page, we need ++ * to issue a special "write enable" command. ++ */ ++ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; ++ ++ if (tg3_nvram_exec_cmd(tp, nvram_cmd)) ++ break; ++ ++ /* Erase the target page */ ++ tw32(NVRAM_ADDR, phy_addr); ++ ++ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR | ++ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE; ++ ++ if (tg3_nvram_exec_cmd(tp, nvram_cmd)) ++ break; ++ ++ /* Issue another write enable to start the write. */ ++ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE; ++ ++ if (tg3_nvram_exec_cmd(tp, nvram_cmd)) ++ break; ++ ++ for (j = 0; j < pagesize; j += 4) { ++ u32 data; ++ ++ data = *((u32 *) (tmp + j)); ++ tw32(NVRAM_WRDATA, cpu_to_be32(data)); ++ ++ tw32(NVRAM_ADDR, phy_addr + j); ++ ++ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | ++ NVRAM_CMD_WR; ++ ++ if (j == 0) ++ nvram_cmd |= NVRAM_CMD_FIRST; ++ else if (j == (pagesize - 4)) ++ nvram_cmd |= NVRAM_CMD_LAST; ++ ++ if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) ++ break; ++ } ++ if (ret) ++ break; ++ } ++ ++ nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE; ++ tg3_nvram_exec_cmd(tp, nvram_cmd); ++ ++ kfree(tmp); ++ ++ return ret; ++} ++ ++/* offset and length are dword aligned */ ++static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len, ++ u8 *buf) ++{ ++ int i, ret = 0; ++ ++ for (i = 0; i < len; i += 4, offset += 4) { ++ u32 data, page_off, phy_addr, nvram_cmd; ++ ++ memcpy(&data, buf + i, 4); ++ tw32(NVRAM_WRDATA, cpu_to_be32(data)); ++ ++ page_off = offset % tp->nvram_pagesize; ++ ++ if ((tp->tg3_flags2 & TG3_FLG2_FLASH) && ++ (tp->nvram_jedecnum == JEDEC_ATMEL)) { ++ ++ phy_addr = ((offset / tp->nvram_pagesize) << ++ ATMEL_AT45DB0X1B_PAGE_POS) + page_off; ++ } ++ else { ++ phy_addr = offset; ++ } ++ ++ tw32(NVRAM_ADDR, phy_addr); ++ ++ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR; ++ ++ if ((page_off == 0) || (i == 0)) ++ nvram_cmd |= NVRAM_CMD_FIRST; ++ else if (page_off == (tp->nvram_pagesize - 4)) ++ nvram_cmd |= NVRAM_CMD_LAST; ++ ++ if (i == (len - 4)) ++ nvram_cmd |= NVRAM_CMD_LAST; ++ ++ if ((tp->nvram_jedecnum == JEDEC_ST) && ++ (nvram_cmd & NVRAM_CMD_FIRST)) { ++ ++ if ((ret = tg3_nvram_exec_cmd(tp, ++ NVRAM_CMD_WREN | NVRAM_CMD_GO | ++ NVRAM_CMD_DONE))) ++ ++ break; ++ } ++ if (!(tp->tg3_flags2 & TG3_FLG2_FLASH)) { ++ /* We always do complete word writes to eeprom. */ ++ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST); ++ } ++ ++ if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd))) ++ break; ++ } ++ return ret; ++} ++ ++/* offset and length are dword aligned */ ++static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) ++{ ++ int ret; ++ ++ if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { ++ printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n"); ++ return -EINVAL; ++ } ++ ++ if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { ++ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | ++ GRC_LCLCTRL_GPIO_OE1); ++ udelay(40); ++ } ++ ++ if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) { ++ ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf); ++ } ++ else { ++ u32 grc_mode; ++ ++ tg3_nvram_lock(tp); ++ ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ u32 nvaccess = tr32(NVRAM_ACCESS); ++ ++ tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE); ++ ++ tw32(NVRAM_WRITE1, 0x406); ++ } ++ ++ grc_mode = tr32(GRC_MODE); ++ tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE); ++ ++ if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) || ++ !(tp->tg3_flags2 & TG3_FLG2_FLASH)) { ++ ++ ret = tg3_nvram_write_block_buffered(tp, offset, len, ++ buf); ++ } ++ else { ++ ret = tg3_nvram_write_block_unbuffered(tp, offset, len, ++ buf); ++ } ++ ++ grc_mode = tr32(GRC_MODE); ++ tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE); ++ ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { ++ u32 nvaccess = tr32(NVRAM_ACCESS); ++ ++ tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE); ++ } ++ tg3_nvram_unlock(tp); ++ } ++ ++ if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { ++ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | ++ GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1); ++ udelay(40); ++ } ++ ++ return ret; + } + + struct subsys_tbl_ent { +@@ -7047,11 +7497,19 @@ + tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); + if (val == NIC_SRAM_DATA_SIG_MAGIC) { + u32 nic_cfg, led_cfg; +- u32 nic_phy_id, cfg2; ++ u32 nic_phy_id, ver, cfg2 = 0; + + tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); + tp->nic_sram_data_cfg = nic_cfg; + ++ tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver); ++ ver >>= NIC_SRAM_DATA_VER_SHIFT; ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && ++ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && ++ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703) && ++ (ver > 0) && (ver < 0x100)) ++ tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2); ++ + eeprom_signature_found = 1; + + if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == +@@ -7070,8 +7528,7 @@ + eeprom_phy_id = 0; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { +- tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg); +- led_cfg &= (NIC_SRAM_DATA_CFG_LED_MODE_MASK | ++ led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK | + SHASTA_EXT_LED_MODE_MASK); + } else + led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK; +@@ -7116,9 +7573,8 @@ + tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) + tp->led_ctrl = LED_CTRL_MODE_PHY_2; + +- if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) || +- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || +- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) && ++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && ++ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && + (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) + tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; + +@@ -7130,9 +7586,13 @@ + if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) + tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; + +- tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2); + if (cfg2 & (1 << 17)) + tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; ++ ++ /* serdes signal pre-emphasis in register 0x590 set by */ ++ /* bootcode if bit 18 is set */ ++ if (cfg2 & (1 << 18)) ++ tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS; + } + + /* Reading the PHY ID register can conflict with ASF +@@ -7188,9 +7648,8 @@ + u32 bmsr, adv_reg, tg3_ctrl; + + tg3_readphy(tp, MII_BMSR, &bmsr); +- tg3_readphy(tp, MII_BMSR, &bmsr); +- +- if (bmsr & BMSR_LSTATUS) ++ if (!tg3_readphy(tp, MII_BMSR, &bmsr) && ++ (bmsr & BMSR_LSTATUS)) + goto skip_phy_reset; + + err = tg3_phy_reset(tp); +@@ -7414,6 +7873,9 @@ + tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff; + tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff; + ++ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ++ tp->tg3_flags2 |= TG3_FLG2_HW_TSO; ++ + if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) + tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + +@@ -8302,11 +8764,13 @@ + } + + #if TG3_TSO_SUPPORT != 0 +- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || ++ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { ++ tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; ++ } ++ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || + tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 || +- ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 && +- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) { ++ (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { + tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; + } else { + tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; +diff -Nur linux-2.4.29/drivers/net/tg3.h linux-mips/drivers/net/tg3.h +--- linux-2.4.29/drivers/net/tg3.h 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/net/tg3.h 2005-03-26 11:47:30.485648346 +0100 +@@ -1274,6 +1274,7 @@ + #define GRC_MODE_HOST_STACKUP 0x00010000 + #define GRC_MODE_HOST_SENDBDS 0x00020000 + #define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000 ++#define GRC_MODE_NVRAM_WR_ENABLE 0x00200000 + #define GRC_MODE_NO_RX_PHDR_CSUM 0x00800000 + #define GRC_MODE_IRQ_ON_TX_CPU_ATTN 0x01000000 + #define GRC_MODE_IRQ_ON_RX_CPU_ATTN 0x02000000 +@@ -1366,6 +1367,8 @@ + #define NVRAM_CMD_ERASE 0x00000040 + #define NVRAM_CMD_FIRST 0x00000080 + #define NVRAM_CMD_LAST 0x00000100 ++#define NVRAM_CMD_WREN 0x00010000 ++#define NVRAM_CMD_WRDI 0x00020000 + #define NVRAM_STAT 0x00007004 + #define NVRAM_WRDATA 0x00007008 + #define NVRAM_ADDR 0x0000700c +@@ -1375,8 +1378,18 @@ + #define NVRAM_CFG1_FLASHIF_ENAB 0x00000001 + #define NVRAM_CFG1_BUFFERED_MODE 0x00000002 + #define NVRAM_CFG1_PASS_THRU 0x00000004 ++#define NVRAM_CFG1_STATUS_BITS 0x00000070 + #define NVRAM_CFG1_BIT_BANG 0x00000008 ++#define NVRAM_CFG1_FLASH_SIZE 0x02000000 + #define NVRAM_CFG1_COMPAT_BYPASS 0x80000000 ++#define NVRAM_CFG1_VENDOR_MASK 0x03000003 ++#define FLASH_VENDOR_ATMEL_EEPROM 0x02000000 ++#define FLASH_VENDOR_ATMEL_FLASH_BUFFERED 0x02000003 ++#define FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED 0x00000003 ++#define FLASH_VENDOR_ST 0x03000001 ++#define FLASH_VENDOR_SAIFUN 0x01000003 ++#define FLASH_VENDOR_SST_SMALL 0x00000001 ++#define FLASH_VENDOR_SST_LARGE 0x02000001 + #define NVRAM_CFG2 0x00007018 + #define NVRAM_CFG3 0x0000701c + #define NVRAM_SWARB 0x00007020 +@@ -1396,15 +1409,16 @@ + #define SWARB_REQ1 0x00002000 + #define SWARB_REQ2 0x00004000 + #define SWARB_REQ3 0x00008000 +-#define NVRAM_BUFFERED_PAGE_SIZE 264 +-#define NVRAM_BUFFERED_PAGE_POS 9 + #define NVRAM_ACCESS 0x00007024 + #define ACCESS_ENABLE 0x00000001 + #define ACCESS_WR_ENABLE 0x00000002 +-/* 0x7024 --> 0x7400 unused */ ++#define NVRAM_WRITE1 0x00007028 ++/* 0x702c --> 0x7400 unused */ + + /* 0x7400 --> 0x8000 unused */ + ++#define TG3_EEPROM_MAGIC 0x669955aa ++ + /* 32K Window into NIC internal memory */ + #define NIC_SRAM_WIN_BASE 0x00008000 + +@@ -1438,6 +1452,9 @@ + #define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000 + #define NIC_SRAM_DATA_CFG_NO_GPIO2 0x00100000 + ++#define NIC_SRAM_DATA_VER 0x00000b5c ++#define NIC_SRAM_DATA_VER_SHIFT 16 ++ + #define NIC_SRAM_DATA_PHY_ID 0x00000b74 + #define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000 + #define NIC_SRAM_DATA_PHY_ID2_MASK 0x0000ffff +@@ -2090,6 +2107,9 @@ + #define TG3_FLG2_PHY_JUST_INITTED 0x00001000 + #define TG3_FLG2_PHY_SERDES 0x00002000 + #define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 ++#define TG3_FLG2_FLASH 0x00008000 ++#define TG3_FLG2_HW_TSO 0x00010000 ++#define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000 + + u32 split_mode_max_reqs; + #define SPLIT_MODE_5704_MAX_REQ 3 +@@ -2164,6 +2184,34 @@ + struct tg3_hw_stats *hw_stats; + dma_addr_t stats_mapping; + struct tq_struct reset_task; ++ ++ u32 nvram_size; ++ u32 nvram_pagesize; ++ u32 nvram_jedecnum; ++ ++#define JEDEC_ATMEL 0x1f ++#define JEDEC_ST 0x20 ++#define JEDEC_SAIFUN 0x4f ++#define JEDEC_SST 0xbf ++ ++#define ATMEL_AT24C64_CHIP_SIZE (64 * 1024) ++#define ATMEL_AT24C64_PAGE_SIZE (32) ++ ++#define ATMEL_AT24C512_CHIP_SIZE (512 * 1024) ++#define ATMEL_AT24C512_PAGE_SIZE (128) ++ ++#define ATMEL_AT45DB0X1B_PAGE_POS 9 ++#define ATMEL_AT45DB0X1B_PAGE_SIZE 264 ++ ++#define ATMEL_AT25F512_PAGE_SIZE 256 ++ ++#define ST_M45PEX0_PAGE_SIZE 256 ++ ++#define SAIFUN_SA25F0XX_PAGE_SIZE 256 ++ ++#define SST_25VF0X0_PAGE_SIZE 4098 ++ ++ + }; + + #endif /* !(_T3_H) */ +diff -Nur linux-2.4.29/drivers/net/tulip/21142.c linux-mips/drivers/net/tulip/21142.c +--- linux-2.4.29/drivers/net/tulip/21142.c 2003-06-13 16:51:35.000000000 +0200 ++++ linux-mips/drivers/net/tulip/21142.c 2005-03-26 11:47:31.371502956 +0100 +@@ -14,8 +14,8 @@ + + */ + +-#include "tulip.h" + #include <linux/pci.h> ++#include "tulip.h" + #include <linux/delay.h> + + +diff -Nur linux-2.4.29/drivers/net/tulip/eeprom.c linux-mips/drivers/net/tulip/eeprom.c +--- linux-2.4.29/drivers/net/tulip/eeprom.c 2003-06-13 16:51:35.000000000 +0200 ++++ linux-mips/drivers/net/tulip/eeprom.c 2005-03-26 11:47:31.372502792 +0100 +@@ -14,6 +14,7 @@ + + */ + ++#include <linux/pci.h> + #include "tulip.h" + #include <linux/init.h> + #include <asm/unaligned.h> +diff -Nur linux-2.4.29/drivers/net/tulip/interrupt.c linux-mips/drivers/net/tulip/interrupt.c +--- linux-2.4.29/drivers/net/tulip/interrupt.c 2003-06-13 16:51:35.000000000 +0200 ++++ linux-mips/drivers/net/tulip/interrupt.c 2005-03-26 11:47:31.372502792 +0100 +@@ -14,10 +14,10 @@ + + */ + ++#include <linux/pci.h> + #include "tulip.h" + #include <linux/config.h> + #include <linux/etherdevice.h> +-#include <linux/pci.h> + + + int tulip_rx_copybreak; +diff -Nur linux-2.4.29/drivers/net/tulip/media.c linux-mips/drivers/net/tulip/media.c +--- linux-2.4.29/drivers/net/tulip/media.c 2003-06-13 16:51:35.000000000 +0200 ++++ linux-mips/drivers/net/tulip/media.c 2005-03-26 11:47:31.373502628 +0100 +@@ -18,6 +18,7 @@ + #include <linux/mii.h> + #include <linux/init.h> + #include <linux/delay.h> ++#include <linux/pci.h> + #include "tulip.h" + + +diff -Nur linux-2.4.29/drivers/net/tulip/pnic2.c linux-mips/drivers/net/tulip/pnic2.c +--- linux-2.4.29/drivers/net/tulip/pnic2.c 2003-06-13 16:51:35.000000000 +0200 ++++ linux-mips/drivers/net/tulip/pnic2.c 2005-03-26 11:47:31.374502464 +0100 +@@ -76,8 +76,8 @@ + + + +-#include "tulip.h" + #include <linux/pci.h> ++#include "tulip.h" + #include <linux/delay.h> + + +diff -Nur linux-2.4.29/drivers/net/tulip/pnic.c linux-mips/drivers/net/tulip/pnic.c +--- linux-2.4.29/drivers/net/tulip/pnic.c 2003-06-13 16:51:35.000000000 +0200 ++++ linux-mips/drivers/net/tulip/pnic.c 2005-03-26 11:47:31.374502464 +0100 +@@ -15,6 +15,7 @@ + */ + + #include <linux/kernel.h> ++#include <linux/pci.h> + #include "tulip.h" + + +diff -Nur linux-2.4.29/drivers/net/tulip/timer.c linux-mips/drivers/net/tulip/timer.c +--- linux-2.4.29/drivers/net/tulip/timer.c 2004-08-08 01:26:05.000000000 +0200 ++++ linux-mips/drivers/net/tulip/timer.c 2005-03-26 11:47:31.375502300 +0100 +@@ -14,6 +14,7 @@ + + */ + ++#include <linux/pci.h> + #include "tulip.h" + + +diff -Nur linux-2.4.29/drivers/net/tulip/tulip_core.c linux-mips/drivers/net/tulip/tulip_core.c +--- linux-2.4.29/drivers/net/tulip/tulip_core.c 2004-08-08 01:26:05.000000000 +0200 ++++ linux-mips/drivers/net/tulip/tulip_core.c 2005-03-26 11:47:31.377501972 +0100 +@@ -20,8 +20,8 @@ + + #include <linux/config.h> + #include <linux/module.h> +-#include "tulip.h" + #include <linux/pci.h> ++#include "tulip.h" + #include <linux/init.h> + #include <linux/etherdevice.h> + #include <linux/delay.h> +diff -Nur linux-2.4.29/drivers/net/tulip/tulip.h linux-mips/drivers/net/tulip/tulip.h +--- linux-2.4.29/drivers/net/tulip/tulip.h 2002-11-29 00:53:14.000000000 +0100 ++++ linux-mips/drivers/net/tulip/tulip.h 2005-03-26 11:47:31.375502300 +0100 +@@ -146,6 +146,9 @@ + TxIntr = 0x01, + }; + ++/* bit mask for CSR5 TX/RX process state */ ++#define CSR5_TS 0x00700000 ++#define CSR5_RS 0x000e0000 + + enum tulip_mode_bits { + TxThreshold = (1 << 22), +@@ -484,9 +487,19 @@ + u32 csr6 = inl(ioaddr + CSR6); + + if (csr6 & RxTx) { ++ unsigned i=1300/10; + outl(csr6 & ~RxTx, ioaddr + CSR6); + barrier(); +- (void) inl(ioaddr + CSR6); /* mmio sync */ ++ /* wait until in-flight frame completes. ++ * Max time @ 10BT: 1500*8b/10Mbps == 1200us (+ 100us margin) ++ * Typically expect this loop to end in < 50us on 100BT. ++ */ ++ while (--i && (inl(ioaddr + CSR5) & (CSR5_TS|CSR5_RS))) ++ udelay(10); ++ ++ if (!i) ++ printk (KERN_DEBUG "%s: tulip_stop_rxtx() failed\n", ++ tp->pdev->slot_name); + } + } + diff -Nur linux-2.4.29/drivers/pci/pci.c linux-mips/drivers/pci/pci.c --- linux-2.4.29/drivers/pci/pci.c 2004-11-17 12:54:21.000000000 +0100 +++ linux-mips/drivers/pci/pci.c 2004-11-19 01:28:41.000000000 +0100 @@ -16247,66 +22217,73 @@ diff -Nur linux-2.4.29/drivers/pci/pci.c linux-mips/drivers/pci/pci.c sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); return max; } -diff -Nur linux-2.4.29/drivers/pcmcia/Config.in linux-mips/drivers/pcmcia/Config.in ---- linux-2.4.29/drivers/pcmcia/Config.in 2004-02-18 14:36:31.000000000 +0100 -+++ linux-mips/drivers/pcmcia/Config.in 2004-02-22 06:21:34.000000000 +0100 -@@ -30,16 +30,14 @@ - dep_tristate ' M8xx support' CONFIG_PCMCIA_M8XX $CONFIG_PCMCIA - fi - if [ "$CONFIG_SOC_AU1X00" = "y" ]; then -- dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA -- if [ "$CONFIG_PCMCIA_AU1X00" != "n" ]; then -- bool ' Pb1x00 board support' CONFIG_PCMCIA_PB1X00 -- bool ' Db1x00 board support' CONFIG_PCMCIA_DB1X00 -- bool ' XXS1500 board support' CONFIG_PCMCIA_XXS1500 -- fi -+ dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA - fi - if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then - dep_bool ' SiByte PCMCIA support' CONFIG_PCMCIA_SIBYTE $CONFIG_PCMCIA $CONFIG_BLK_DEV_IDE_SIBYTE - fi -+ if [ "$CONFIG_VRC4171" = "y" -o "$CONFIG_VRC4171" = "m" ]; then -+ dep_tristate ' NEC VRC4171 Card Controllers support' CONFIG_PCMCIA_VRC4171 $CONFIG_PCMCIA -+ fi - if [ "$CONFIG_VRC4173" = "y" -o "$CONFIG_VRC4173" = "m" ]; then - dep_tristate ' NEC VRC4173 CARDU support' CONFIG_PCMCIA_VRC4173 $CONFIG_PCMCIA - fi -diff -Nur linux-2.4.29/drivers/pcmcia/Makefile linux-mips/drivers/pcmcia/Makefile ---- linux-2.4.29/drivers/pcmcia/Makefile 2004-02-18 14:36:31.000000000 +0100 -+++ linux-mips/drivers/pcmcia/Makefile 2005-02-12 04:06:57.000000000 +0100 -@@ -61,9 +61,18 @@ - - obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o - au1000_ss-objs-y := au1000_generic.o --au1000_ss-objs-$(CONFIG_PCMCIA_PB1X00) += au1000_pb1x00.o --au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o --au1000_ss-objs-$(CONFIG_PCMCIA_XXS1500) += au1000_xxs1500.o -+au1000_ss-objs-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_PB1550) += au1000_pb1550.o -+au1000_ss-objs-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o -+au1000_ss-objs-$(CONFIG_MIPS_HYDROGEN3) += au1000_hydrogen3.o -+au1000_ss-objs-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o +diff -Nur linux-2.4.29/drivers/pci/quirks.c linux-mips/drivers/pci/quirks.c +--- linux-2.4.29/drivers/pci/quirks.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/pci/quirks.c 2005-03-26 11:47:31.393499346 +0100 +@@ -368,9 +368,6 @@ + * non-x86 architectures (yes Via exists on PPC among other places), + * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get + * interrupts delivered properly. +- * +- * TODO: When we have device-specific interrupt routers, +- * quirk_via_irqpic will go away from quirks. + */ - obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o - obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o -@@ -89,6 +98,7 @@ - sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o - sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o + /* +@@ -393,22 +390,6 @@ + d->irq = irq; + } -+obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o - obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o +-static void __init quirk_via_irqpic(struct pci_dev *dev) +-{ +- u8 irq, new_irq = dev->irq & 0xf; +- +- pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); +- +- if (new_irq != irq) { +- printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n", +- dev->slot_name, irq, new_irq); +- +- udelay(15); +- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); +- } +-} +- +- + /* + * PIIX3 USB: We have to disable USB interrupts that are + * hardwired to PIRQD# and may be shared with an +@@ -639,12 +620,14 @@ + * VIA northbridges care about PCI_INTERRUPT_LINE + */ + +-int interrupt_line_quirk; ++int via_interrupt_line_quirk; - include $(TOPDIR)/Rules.make + static void __init quirk_via_bridge(struct pci_dev *pdev) + { +- if(pdev->devfn == 0) +- interrupt_line_quirk = 1; ++ if(pdev->devfn == 0) { ++ printk(KERN_INFO "PCI: Via IRQ fixup\n"); ++ via_interrupt_line_quirk = 1; ++ } + } + + /* +@@ -773,9 +756,6 @@ + #endif + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, +- { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic }, +- { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic }, +- { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic }, + + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering }, diff -Nur linux-2.4.29/drivers/pcmcia/au1000_db1x00.c linux-mips/drivers/pcmcia/au1000_db1x00.c --- linux-2.4.29/drivers/pcmcia/au1000_db1x00.c 2005-01-19 15:09:57.000000000 +0100 -+++ linux-mips/drivers/pcmcia/au1000_db1x00.c 2005-02-12 04:06:57.000000000 +0100 ++++ linux-mips/drivers/pcmcia/au1000_db1x00.c 2005-03-26 11:47:31.434492618 +0100 @@ -1,6 +1,6 @@ /* * @@ -16379,6 +22356,74 @@ diff -Nur linux-2.4.29/drivers/pcmcia/au1000_db1x00.c linux-mips/drivers/pcmcia/ return 0; } +diff -Nur linux-2.4.29/drivers/pcmcia/cistpl.c linux-mips/drivers/pcmcia/cistpl.c +--- linux-2.4.29/drivers/pcmcia/cistpl.c 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/pcmcia/cistpl.c 2005-03-26 11:47:31.435492454 +0100 +@@ -140,7 +140,6 @@ + } else { + u_int inc = 1; + if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; } +- sys += (addr & (s->cap.map_size-1)); + mem->card_start = addr & ~(s->cap.map_size-1); + while (len) { + set_cis_map(s, mem); +diff -Nur linux-2.4.29/drivers/pcmcia/Config.in linux-mips/drivers/pcmcia/Config.in +--- linux-2.4.29/drivers/pcmcia/Config.in 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/pcmcia/Config.in 2004-02-22 06:21:34.000000000 +0100 +@@ -30,16 +30,14 @@ + dep_tristate ' M8xx support' CONFIG_PCMCIA_M8XX $CONFIG_PCMCIA + fi + if [ "$CONFIG_SOC_AU1X00" = "y" ]; then +- dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA +- if [ "$CONFIG_PCMCIA_AU1X00" != "n" ]; then +- bool ' Pb1x00 board support' CONFIG_PCMCIA_PB1X00 +- bool ' Db1x00 board support' CONFIG_PCMCIA_DB1X00 +- bool ' XXS1500 board support' CONFIG_PCMCIA_XXS1500 +- fi ++ dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA + fi + if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then + dep_bool ' SiByte PCMCIA support' CONFIG_PCMCIA_SIBYTE $CONFIG_PCMCIA $CONFIG_BLK_DEV_IDE_SIBYTE + fi ++ if [ "$CONFIG_VRC4171" = "y" -o "$CONFIG_VRC4171" = "m" ]; then ++ dep_tristate ' NEC VRC4171 Card Controllers support' CONFIG_PCMCIA_VRC4171 $CONFIG_PCMCIA ++ fi + if [ "$CONFIG_VRC4173" = "y" -o "$CONFIG_VRC4173" = "m" ]; then + dep_tristate ' NEC VRC4173 CARDU support' CONFIG_PCMCIA_VRC4173 $CONFIG_PCMCIA + fi +diff -Nur linux-2.4.29/drivers/pcmcia/Makefile linux-mips/drivers/pcmcia/Makefile +--- linux-2.4.29/drivers/pcmcia/Makefile 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/pcmcia/Makefile 2005-03-26 11:47:31.433492782 +0100 +@@ -61,9 +61,18 @@ + + obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o + au1000_ss-objs-y := au1000_generic.o +-au1000_ss-objs-$(CONFIG_PCMCIA_PB1X00) += au1000_pb1x00.o +-au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o +-au1000_ss-objs-$(CONFIG_PCMCIA_XXS1500) += au1000_xxs1500.o ++au1000_ss-objs-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_PB1550) += au1000_pb1550.o ++au1000_ss-objs-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o ++au1000_ss-objs-$(CONFIG_MIPS_HYDROGEN3) += au1000_hydrogen3.o ++au1000_ss-objs-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o + + obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o + obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o +@@ -89,6 +98,7 @@ + sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o + sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o + ++obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o + obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o + + include $(TOPDIR)/Rules.make diff -Nur linux-2.4.29/drivers/pcmcia/vrc4171_card.c linux-mips/drivers/pcmcia/vrc4171_card.c --- linux-2.4.29/drivers/pcmcia/vrc4171_card.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/drivers/pcmcia/vrc4171_card.c 2004-01-19 16:54:58.000000000 +0100 @@ -17269,6 +23314,2768 @@ diff -Nur linux-2.4.29/drivers/pcmcia/vrc4171_card.c linux-mips/drivers/pcmcia/v + +module_init(vrc4171_card_init); +module_exit(vrc4171_card_exit); +diff -Nur linux-2.4.29/drivers/sbus/audio/audio.c linux-mips/drivers/sbus/audio/audio.c +--- linux-2.4.29/drivers/sbus/audio/audio.c 2001-10-11 08:42:46.000000000 +0200 ++++ linux-mips/drivers/sbus/audio/audio.c 2005-03-26 11:47:32.089385135 +0100 +@@ -65,6 +65,14 @@ + #define tprintk(x) + #endif + ++static int audio_input_buffers = 8; ++MODULE_PARM(audio_input_buffers, "i"); ++MODULE_PARM_DESC(audio_input_buffers,"Number of input 8KB buffers."); ++ ++static int audio_output_buffers = 8; ++MODULE_PARM(audio_output_buffers, "i"); ++MODULE_PARM_DESC(audio_output_buffers,"Number of output 8KB buffer."); ++ + static short lis_get_elist_ent( strevent_t *list, pid_t pid ); + static int lis_add_to_elist( strevent_t **list, pid_t pid, short events ); + static int lis_del_from_elist( strevent_t **list, pid_t pid, short events ); +@@ -438,7 +446,7 @@ + m = drv->ops->get_input_balance(drv); + i = OSS_TO_GAIN(k); + j = OSS_TO_BAL(k); +- oprintk((" for stereo to do %d (bal %d):", i, j)); ++ oprintk((" for stereo to do %ld (bal %ld):", i, j)); + if (drv->ops->set_input_volume) + drv->ops->set_input_volume(drv, i); + if (drv->ops->set_input_balance) +@@ -488,7 +496,7 @@ + oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m))); + i = OSS_TO_GAIN(k); + j = OSS_TO_BAL(k); +- oprintk((" for stereo to %d (bal %d)\n", i, j)); ++ oprintk((" for stereo to %ld (bal %ld)\n", i, j)); + if (drv->ops->set_output_volume) + drv->ops->set_output_volume(drv, i); + if (drv->ops->set_output_balance) +@@ -565,7 +573,7 @@ + if (k & SOUND_MASK_CD) j = AUDIO_CD; + if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN; + if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE; +- oprintk(("setting inport to %d\n", j)); ++ oprintk(("setting inport to %ld\n", j)); + i = drv->ops->set_input_port(drv, j); + + return put_user(i, (int *)arg); +@@ -798,7 +806,7 @@ + retval = -EINVAL; + break; + } +- get_user(i, (int *)arg) ++ get_user(i, (int *)arg); + tprintk(("setting speed to %d\n", i)); + drv->ops->set_input_rate(drv, i); + drv->ops->set_output_rate(drv, i); +@@ -1955,8 +1963,6 @@ + * Input buffers, on the other hand, always fill completely, + * so we don't need input counts - each contains input_buffer_size + * bytes of audio data. +- * +- * TODO: Make number of input/output buffers tunable parameters + */ + + init_waitqueue_head(&drv->open_wait); +@@ -1964,7 +1970,7 @@ + init_waitqueue_head(&drv->output_drain_wait); + init_waitqueue_head(&drv->input_read_wait); + +- drv->num_output_buffers = 8; ++ drv->num_output_buffers = audio_output_buffers; + drv->output_buffer_size = (4096 * 2); + drv->playing_count = 0; + drv->output_offset = 0; +@@ -1997,7 +2003,7 @@ + } + + /* Setup the circular queue of input buffers. */ +- drv->num_input_buffers = 8; ++ drv->num_input_buffers = audio_input_buffers; + drv->input_buffer_size = (4096 * 2); + drv->recording_count = 0; + drv->input_front = 0; +diff -Nur linux-2.4.29/drivers/sbus/audio/dbri.c linux-mips/drivers/sbus/audio/dbri.c +--- linux-2.4.29/drivers/sbus/audio/dbri.c 2002-11-29 00:53:14.000000000 +0100 ++++ linux-mips/drivers/sbus/audio/dbri.c 2005-03-26 11:47:32.378337711 +0100 +@@ -51,6 +51,7 @@ + #include <linux/slab.h> + #include <linux/version.h> + #include <linux/delay.h> ++#include <linux/soundcard.h> + #include <asm/openprom.h> + #include <asm/oplib.h> + #include <asm/system.h> +@@ -161,7 +162,7 @@ + + static void dbri_process_interrupt_buffer(struct dbri *); + +-static void dbri_cmdsend(struct dbri *dbri, volatile s32 *cmd) ++static void dbri_cmdsend(struct dbri *dbri, volatile s32 *cmd, int pause) + { + int MAXLOOPS = 1000000; + int maxloops = MAXLOOPS; +@@ -181,25 +182,30 @@ + } else if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS-1) { + printk("DBRI: Command buffer overflow! (bug in driver)\n"); + } else { +- *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); ++ if (pause) ++ *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); + *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); + dbri->wait_seen = 0; + sbus_writel(dbri->dma_dvma, dbri->regs + REG8); +- while ((--maxloops) > 0 && +- (sbus_readl(dbri->regs + REG0) & D_P)) +- barrier(); +- if (maxloops == 0) { +- printk("DBRI: Chip never completed command buffer\n"); +- } else { +- while ((--maxloops) > 0 && (! dbri->wait_seen)) +- dbri_process_interrupt_buffer(dbri); ++ if (pause) { ++ while ((--maxloops) > 0 && ++ (sbus_readl(dbri->regs + REG0) & D_P)) ++ barrier(); + if (maxloops == 0) { +- printk("DBRI: Chip never acked WAIT\n"); ++ printk("DBRI: Chip never completed command buffer\n"); + } else { +- dprintk(D_INT, ("DBRI: Chip completed command " +- "buffer (%d)\n", +- MAXLOOPS - maxloops)); ++ while ((--maxloops) > 0 && (! dbri->wait_seen)) ++ dbri_process_interrupt_buffer(dbri); ++ if (maxloops == 0) { ++ printk("DBRI: Chip never acked WAIT\n"); ++ } else { ++ dprintk(D_INT, ("DBRI: Chip completed command " ++ "buffer (%d)\n", ++ MAXLOOPS - maxloops)); ++ } + } ++ } else { ++ dprintk(D_INT, ("DBRI: NO PAUSE\n")); + } + } + +@@ -257,7 +263,10 @@ + /* We should query the openprom to see what burst sizes this + * SBus supports. For now, just disable all SBus bursts */ + tmp = sbus_readl(dbri->regs + REG0); +- tmp &= ~(D_G | D_S | D_E); ++ /* A brute approach - DBRI falls back to working burst size by itself ++ * On SS20 D_S does not work, so do not try so high. */ ++ tmp |= D_G | D_E; ++ tmp &= ~D_S; + sbus_writel(tmp, dbri->regs + REG0); + + /* +@@ -268,7 +277,7 @@ + *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); + *(cmd++) = dma_addr; + +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + } + + +@@ -455,7 +464,7 @@ + dbri->pipes[pipe].sdp + | D_SDP_P | D_SDP_C | D_SDP_2SAME); + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td); +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + } + + if (code == D_INTR_FXDT) { +@@ -579,7 +588,7 @@ + cmd = dbri_cmdlock(dbri); + *(cmd++) = DBRI_CMD(D_SDP, 0, sdp | D_SDP_C | D_SDP_P); + *(cmd++) = 0; +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + + desc = dbri->pipes[pipe].desc; + while (desc != -1) { +@@ -722,7 +731,7 @@ + *(cmd++) = D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); + } + +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + } + + /* I don't use this function, so it's basically untested. */ +@@ -752,7 +761,7 @@ + *(cmd++) = D_TS_NEXT(nextpipe); + } + +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + } + + /* xmit_fixed() / recv_fixed() +@@ -803,7 +812,7 @@ + *(cmd++) = DBRI_CMD(D_SSP, 0, pipe); + *(cmd++) = data; + +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + } + + static void recv_fixed(struct dbri *dbri, int pipe, volatile __u32 *ptr) +@@ -884,7 +893,9 @@ + } + + if (len > ((1 << 13) - 1)) { +- mylen = (1 << 13) - 1; ++ /* One should not leave a buffer shorter than */ ++ /* a single sample. Otherwise bad things happens.*/ ++ mylen = (1 << 13) - 4; + } else { + mylen = len; + } +@@ -954,7 +965,7 @@ + + cmd = dbri_cmdlock(dbri); + *(cmd++) = DBRI_CMD(D_CDP, 0, pipe); +- dbri_cmdsend(dbri,cmd); ++ dbri_cmdsend(dbri,cmd, 0); + } else { + /* Pipe isn't active - issue an SDP command to start + * our chain of TDs running. +@@ -965,7 +976,7 @@ + dbri->pipes[pipe].sdp + | D_SDP_P | D_SDP_EVERY | D_SDP_C); + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 0); + } + + restore_flags(flags); +@@ -1083,7 +1094,7 @@ + *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_C); + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_rd); + +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + } + + +@@ -1191,7 +1202,7 @@ + *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); + *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN); + +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + } + + /* +@@ -1538,7 +1549,6 @@ + xmit_on_pipe(dbri, 4, buffer, count, + &dbri_audio_output_callback, drv); + +-#if 0 + /* Notify midlevel that we're a DMA-capable driver that + * can accept another buffer immediately. We should probably + * check that we've got enough resources (i.e, descriptors) +@@ -1551,9 +1561,14 @@ + * DBRI with a chain of buffers, but the midlevel code is + * so tricky that I really don't want to deal with it. + */ ++ /* ++ * This must be enabled otherwise the output is noisy ++ * as return to user space is done when all buffers ++ * are already played, so user space player has no time ++ * to prepare next ones without a period of silence. - Krzysztof Helt ++ */ + + sparcaudio_output_done(drv, 2); +-#endif + } + + static void dbri_stop_output(struct sparcaudio_driver *drv) +@@ -1842,6 +1857,12 @@ + return dbri_get_output_rate(drv); + } + ++static int dbri_get_formats(struct sparcaudio_driver *drv) ++{ ++/* 8-bit format is not working */ ++ return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE); ++} ++ + /******************* sparcaudio midlevel - ports ***********************/ + + static int dbri_set_output_port(struct sparcaudio_driver *drv, int port) +@@ -1983,6 +2004,19 @@ + dbri_get_input_ports, + dbri_set_output_muted, + dbri_get_output_muted, ++ NULL, /* dbri_set_output_pause, */ ++ NULL, /* dbri_get_output_pause, */ ++ NULL, /* dbri_set_input_pause, */ ++ NULL, /* dbri_get_input_pause, */ ++ NULL, /* dbri_set_output_samples, */ ++ NULL, /* dbri_get_output_samples, */ ++ NULL, /* dbri_set_input_samples, */ ++ NULL, /* dbri_get_input_samples, */ ++ NULL, /* dbri_set_output_error, */ ++ NULL, /* dbri_get_output_error, */ ++ NULL, /* dbri_set_input_error, */ ++ NULL, /* dbri_get_input_error, */ ++ dbri_get_formats + }; + + +@@ -2093,7 +2127,7 @@ + #endif + *(cmd++) = DBRI_CMD(D_TE, 0, val); + +- dbri_cmdsend(dbri, cmd); ++ dbri_cmdsend(dbri, cmd, 1); + + /* Activate the interface */ + tmp = sbus_readl(dbri->regs + REG0); +diff -Nur linux-2.4.29/drivers/scsi/ahci.c linux-mips/drivers/scsi/ahci.c +--- linux-2.4.29/drivers/scsi/ahci.c 2005-01-19 15:10:01.000000000 +0100 ++++ linux-mips/drivers/scsi/ahci.c 2005-03-26 11:47:32.448326225 +0100 +@@ -40,8 +40,6 @@ + #define DRV_NAME "ahci" + #define DRV_VERSION "1.00" + +-#define msleep libata_msleep /* 2.4-specific */ +- + enum { + AHCI_PCI_BAR = 5, + AHCI_MAX_SG = 168, /* hardware max is 64K */ +@@ -180,6 +178,7 @@ + static void ahci_host_stop(struct ata_host_set *host_set); + static void ahci_qc_prep(struct ata_queued_cmd *qc); + static u8 ahci_check_status(struct ata_port *ap); ++static u8 ahci_check_err(struct ata_port *ap); + static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); + + static Scsi_Host_Template ahci_sht = { +@@ -206,6 +205,8 @@ + .port_disable = ata_port_disable, + + .check_status = ahci_check_status, ++ .check_altstatus = ahci_check_status, ++ .check_err = ahci_check_err, + .dev_select = ata_noop_dev_select, + + .phy_reset = ahci_phy_reset, +@@ -248,6 +249,12 @@ + board_ahci }, /* ICH7 */ + { PCI_VENDOR_ID_INTEL, 0x27c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* ICH7M */ ++ { PCI_VENDOR_ID_INTEL, 0x27c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ board_ahci }, /* ICH7R */ ++ { PCI_VENDOR_ID_INTEL, 0x27c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ board_ahci }, /* ICH7R */ ++ { PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ board_ahci }, /* ULi M5288 */ + { } /* terminate list */ + }; + +@@ -448,6 +455,13 @@ + return readl(mmio + PORT_TFDATA) & 0xFF; + } + ++static u8 ahci_check_err(struct ata_port *ap) ++{ ++ void *mmio = (void *) ap->ioaddr.cmd_addr; ++ ++ return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF; ++} ++ + static void ahci_fill_sg(struct ata_queued_cmd *qc) + { + struct ahci_port_priv *pp = qc->ap->private_data; +@@ -515,15 +529,6 @@ + ahci_fill_sg(qc); + } + +-static inline void ahci_dma_complete (struct ata_port *ap, +- struct ata_queued_cmd *qc, +- int have_err) +-{ +- /* get drive status; clear intr; complete txn */ +- ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), +- have_err ? ATA_ERR : 0); +-} +- + static void ahci_intr_error(struct ata_port *ap, u32 irq_stat) + { + void *mmio = ap->host_set->mmio_base; +@@ -569,7 +574,7 @@ + writel(tmp, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ + +- printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->port_no); ++ printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id); + } + + static void ahci_eng_timeout(struct ata_port *ap) +@@ -761,10 +766,10 @@ + + using_dac = hpriv->cap & HOST_CAP_64; + if (using_dac && +- !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { ++ !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + hpriv->flags |= HOST_CAP_64; + } else { +- rc = pci_set_dma_mask(pdev, 0xffffffffULL); ++ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n", + pci_name(pdev)); +@@ -929,6 +934,7 @@ + unsigned long base; + void *mmio_base; + unsigned int board_idx = (unsigned int) ent->driver_data; ++ int pci_dev_busy = 0; + int rc; + + VPRINTK("ENTER\n"); +@@ -941,8 +947,10 @@ + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + pci_enable_intx(pdev); + +@@ -1002,7 +1010,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + } + +diff -Nur linux-2.4.29/drivers/scsi/aic7xxx/aic79xx_pci.c linux-mips/drivers/scsi/aic7xxx/aic79xx_pci.c +--- linux-2.4.29/drivers/scsi/aic7xxx/aic79xx_pci.c 2003-08-25 13:44:42.000000000 +0200 ++++ linux-mips/drivers/scsi/aic7xxx/aic79xx_pci.c 2005-03-26 11:47:34.828935512 +0100 +@@ -451,8 +451,10 @@ + * or read prefetching could be initiated by the + * CPU or host bridge. Our device does not support + * either, so look for data corruption and/or flaged +- * PCI errors. ++ * PCI errors. First pause without causing another ++ * chip reset. + */ ++ hcntrl &= ~CHIPRST; + ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); + while (ahd_is_paused(ahd) == 0) + ; +diff -Nur linux-2.4.29/drivers/scsi/aic7xxx/aic7xxx_pci.c linux-mips/drivers/scsi/aic7xxx/aic7xxx_pci.c +--- linux-2.4.29/drivers/scsi/aic7xxx/aic7xxx_pci.c 2003-08-25 13:44:42.000000000 +0200 ++++ linux-mips/drivers/scsi/aic7xxx/aic7xxx_pci.c 2005-03-26 11:47:34.831935020 +0100 +@@ -1284,8 +1284,10 @@ + * or read prefetching could be initiated by the + * CPU or host bridge. Our device does not support + * either, so look for data corruption and/or flagged +- * PCI errors. ++ * PCI errors. First pause without causing another ++ * chip reset. + */ ++ hcntrl &= ~CHIPRST; + ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); + while (ahc_is_paused(ahc) == 0) + ; +diff -Nur linux-2.4.29/drivers/scsi/ata_piix.c linux-mips/drivers/scsi/ata_piix.c +--- linux-2.4.29/drivers/scsi/ata_piix.c 2005-01-19 15:10:01.000000000 +0100 ++++ linux-mips/drivers/scsi/ata_piix.c 2005-03-26 11:47:32.450325897 +0100 +@@ -139,6 +139,8 @@ + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + +@@ -164,6 +166,8 @@ + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + +diff -Nur linux-2.4.29/drivers/scsi/Config.in linux-mips/drivers/scsi/Config.in +--- linux-2.4.29/drivers/scsi/Config.in 2005-01-19 15:09:59.000000000 +0100 ++++ linux-mips/drivers/scsi/Config.in 2005-03-26 11:47:32.437328030 +0100 +@@ -73,6 +73,7 @@ + dep_tristate ' ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SVW $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL + dep_tristate ' Intel PIIX/ICH SATA support' CONFIG_SCSI_ATA_PIIX $CONFIG_SCSI_SATA $CONFIG_PCI + dep_tristate ' NVIDIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_NV $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL ++dep_tristate ' Pacific Digital SATA QStor support' CONFIG_SCSI_SATA_QSTOR $CONFIG_SCSI_SATA $CONFIG_PCI + dep_tristate ' Promise SATA TX2/TX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_PROMISE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL + dep_tristate ' Promise SATA SX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SX4 $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL + dep_tristate ' Silicon Image SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL +diff -Nur linux-2.4.29/drivers/scsi/libata-core.c linux-mips/drivers/scsi/libata-core.c +--- linux-2.4.29/drivers/scsi/libata-core.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/libata-core.c 2005-03-26 11:47:32.481320810 +0100 +@@ -376,7 +376,7 @@ + } + + /** +- * ata_check_status - Read device status reg & clear interrupt ++ * ata_check_status_pio - Read device status reg & clear interrupt + * @ap: port where the device is + * + * Reads ATA taskfile status register for currently-selected device +@@ -414,6 +414,27 @@ + return ata_check_status_pio(ap); + } + ++u8 ata_altstatus(struct ata_port *ap) ++{ ++ if (ap->ops->check_altstatus) ++ return ap->ops->check_altstatus(ap); ++ ++ if (ap->flags & ATA_FLAG_MMIO) ++ return readb((void __iomem *)ap->ioaddr.altstatus_addr); ++ return inb(ap->ioaddr.altstatus_addr); ++} ++ ++u8 ata_chk_err(struct ata_port *ap) ++{ ++ if (ap->ops->check_err) ++ return ap->ops->check_err(ap); ++ ++ if (ap->flags & ATA_FLAG_MMIO) { ++ return readb((void __iomem *) ap->ioaddr.error_addr); ++ } ++ return inb(ap->ioaddr.error_addr); ++} ++ + /** + * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure + * @tf: Taskfile to convert +@@ -1160,7 +1181,6 @@ + printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", + ap->id, device); + err_out: +- ata_irq_on(ap); /* re-enable interrupts */ + dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */ + DPRINTK("EXIT, err\n"); + } +@@ -1668,7 +1688,8 @@ + ata_dev_try_classify(ap, 1); + + /* re-enable interrupts */ +- ata_irq_on(ap); ++ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ ++ ata_irq_on(ap); + + /* is double-select really necessary? */ + if (ap->device[1].class != ATA_DEV_NONE) +@@ -1699,6 +1720,69 @@ + DPRINTK("EXIT\n"); + } + ++static void ata_pr_blacklisted(struct ata_port *ap, struct ata_device *dev) ++{ ++ printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n", ++ ap->id, dev->devno); ++} ++ ++static const char * ata_dma_blacklist [] = { ++ "WDC AC11000H", ++ "WDC AC22100H", ++ "WDC AC32500H", ++ "WDC AC33100H", ++ "WDC AC31600H", ++ "WDC AC32100H", ++ "WDC AC23200L", ++ "Compaq CRD-8241B", ++ "CRD-8400B", ++ "CRD-8480B", ++ "CRD-8482B", ++ "CRD-84", ++ "SanDisk SDP3B", ++ "SanDisk SDP3B-64", ++ "SANYO CD-ROM CRD", ++ "HITACHI CDR-8", ++ "HITACHI CDR-8335", ++ "HITACHI CDR-8435", ++ "Toshiba CD-ROM XM-6202B", ++ "CD-532E-A", ++ "E-IDE CD-ROM CR-840", ++ "CD-ROM Drive/F5A", ++ "WPI CDD-820", ++ "SAMSUNG CD-ROM SC-148C", ++ "SAMSUNG CD-ROM SC", ++ "SanDisk SDP3B-64", ++ "SAMSUNG CD-ROM SN-124", ++ "ATAPI CD-ROM DRIVE 40X MAXIMUM", ++ "_NEC DV5800A", ++}; ++ ++static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev) ++{ ++ unsigned char model_num[40]; ++ char *s; ++ unsigned int len; ++ int i; ++ ++ ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, ++ sizeof(model_num)); ++ s = &model_num[0]; ++ len = strnlen(s, sizeof(model_num)); ++ ++ /* ATAPI specifies that empty space is blank-filled; remove blanks */ ++ while ((len > 0) && (s[len - 1] == ' ')) { ++ len--; ++ s[len] = 0; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) ++ if (!strncmp(ata_dma_blacklist[i], s, len)) ++ return 1; ++ ++ return 0; ++} ++ + static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift) + { + struct ata_device *master, *slave; +@@ -1711,17 +1795,37 @@ + + if (shift == ATA_SHIFT_UDMA) { + mask = ap->udma_mask; +- if (ata_dev_present(master)) ++ if (ata_dev_present(master)) { + mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); +- if (ata_dev_present(slave)) ++ if (ata_dma_blacklisted(ap, master)) { ++ mask = 0; ++ ata_pr_blacklisted(ap, master); ++ } ++ } ++ if (ata_dev_present(slave)) { + mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); ++ if (ata_dma_blacklisted(ap, slave)) { ++ mask = 0; ++ ata_pr_blacklisted(ap, slave); ++ } ++ } + } + else if (shift == ATA_SHIFT_MWDMA) { + mask = ap->mwdma_mask; +- if (ata_dev_present(master)) ++ if (ata_dev_present(master)) { + mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07); +- if (ata_dev_present(slave)) ++ if (ata_dma_blacklisted(ap, master)) { ++ mask = 0; ++ ata_pr_blacklisted(ap, master); ++ } ++ } ++ if (ata_dev_present(slave)) { + mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); ++ if (ata_dma_blacklisted(ap, slave)) { ++ mask = 0; ++ ata_pr_blacklisted(ap, slave); ++ } ++ } + } + else if (shift == ATA_SHIFT_PIO) { + mask = ap->pio_mask; +@@ -2518,10 +2622,10 @@ + + case ATA_PROT_DMA: + case ATA_PROT_ATAPI_DMA: +- host_stat = ata_bmdma_status(ap); ++ host_stat = ap->ops->bmdma_status(ap); + + /* before we do anything else, clear DMA-Start bit */ +- ata_bmdma_stop(ap); ++ ap->ops->bmdma_stop(ap); + + /* fall through */ + +@@ -2530,7 +2634,7 @@ + drv_stat = ata_chk_status(ap); + + /* ack bmdma irq events */ +- ata_bmdma_ack_irq(ap); ++ ap->ops->irq_clear(ap); + + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", + ap->id, qc->tf.command, drv_stat, host_stat); +@@ -2669,6 +2773,24 @@ + } + + /** ++ * ata_qc_free - free unused ata_queued_cmd ++ * @qc: Command to complete ++ * ++ * Designed to free unused ata_queued_cmd object ++ * in case something prevents using it. ++ * ++ * LOCKING: ++ * ++ */ ++void ata_qc_free(struct ata_queued_cmd *qc) ++{ ++ assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ ++ assert(qc->waiting == NULL); /* nothing should be waiting */ ++ ++ __ata_qc_complete(qc); ++} ++ ++/** + * ata_qc_complete - Complete an active ATA command + * @qc: Command to complete + * @drv_stat: ATA status register contents +@@ -2717,7 +2839,7 @@ + return 1; + + /* fall through */ +- ++ + default: + return 0; + } +@@ -2959,7 +3081,43 @@ + + void ata_bmdma_irq_clear(struct ata_port *ap) + { +- ata_bmdma_ack_irq(ap); ++ if (ap->flags & ATA_FLAG_MMIO) { ++ void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; ++ writeb(readb(mmio), mmio); ++ } else { ++ unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; ++ outb(inb(addr), addr); ++ } ++ ++} ++ ++u8 ata_bmdma_status(struct ata_port *ap) ++{ ++ u8 host_stat; ++ if (ap->flags & ATA_FLAG_MMIO) { ++ void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; ++ host_stat = readb(mmio + ATA_DMA_STATUS); ++ } else ++ host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); ++ return host_stat; ++} ++ ++void ata_bmdma_stop(struct ata_port *ap) ++{ ++ if (ap->flags & ATA_FLAG_MMIO) { ++ void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; ++ ++ /* clear start/stop bit */ ++ writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, ++ mmio + ATA_DMA_CMD); ++ } else { ++ /* clear start/stop bit */ ++ outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, ++ ap->ioaddr.bmdma_addr + ATA_DMA_CMD); ++ } ++ ++ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ ++ ata_altstatus(ap); /* dummy read */ + } + + /** +@@ -2989,7 +3147,7 @@ + case ATA_PROT_ATAPI_DMA: + case ATA_PROT_ATAPI: + /* check status of DMA engine */ +- host_stat = ata_bmdma_status(ap); ++ host_stat = ap->ops->bmdma_status(ap); + VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); + + /* if it's not our irq... */ +@@ -2997,7 +3155,7 @@ + goto idle_irq; + + /* before we do anything else, clear DMA-Start bit */ +- ata_bmdma_stop(ap); ++ ap->ops->bmdma_stop(ap); + + /* fall through */ + +@@ -3016,7 +3174,7 @@ + ap->id, qc->tf.protocol, status); + + /* ack bmdma irq events */ +- ata_bmdma_ack_irq(ap); ++ ap->ops->irq_clear(ap); + + /* complete taskfile transaction */ + ata_qc_complete(qc, status); +@@ -3470,32 +3628,28 @@ + } + + static struct ata_probe_ent * +-ata_probe_ent_alloc(int n, struct device *dev, struct ata_port_info **port) ++ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port) + { + struct ata_probe_ent *probe_ent; +- int i; + +- probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL); ++ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) { + printk(KERN_ERR DRV_NAME "(%s): out of memory\n", + pci_name(to_pci_dev(dev))); + return NULL; + } + +- memset(probe_ent, 0, sizeof(*probe_ent) * n); ++ memset(probe_ent, 0, sizeof(*probe_ent)); + +- for (i = 0; i < n; i++) { +- INIT_LIST_HEAD(&probe_ent[i].node); +- probe_ent[i].dev = dev; +- +- probe_ent[i].sht = port[i]->sht; +- probe_ent[i].host_flags = port[i]->host_flags; +- probe_ent[i].pio_mask = port[i]->pio_mask; +- probe_ent[i].mwdma_mask = port[i]->mwdma_mask; +- probe_ent[i].udma_mask = port[i]->udma_mask; +- probe_ent[i].port_ops = port[i]->port_ops; ++ INIT_LIST_HEAD(&probe_ent->node); ++ probe_ent->dev = dev; + +- } ++ probe_ent->sht = port->sht; ++ probe_ent->host_flags = port->host_flags; ++ probe_ent->pio_mask = port->pio_mask; ++ probe_ent->mwdma_mask = port->mwdma_mask; ++ probe_ent->udma_mask = port->udma_mask; ++ probe_ent->port_ops = port->port_ops; + + return probe_ent; + } +@@ -3505,7 +3659,7 @@ + ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) + { + struct ata_probe_ent *probe_ent = +- ata_probe_ent_alloc(1, pci_dev_to_dev(pdev), port); ++ ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); + if (!probe_ent) + return NULL; + +@@ -3531,39 +3685,47 @@ + return probe_ent; + } + +-struct ata_probe_ent * +-ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port) ++static struct ata_probe_ent * ++ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port, ++ struct ata_probe_ent **ppe2) + { +- struct ata_probe_ent *probe_ent = +- ata_probe_ent_alloc(2, pci_dev_to_dev(pdev), port); ++ struct ata_probe_ent *probe_ent, *probe_ent2; ++ ++ probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); + if (!probe_ent) + return NULL; ++ probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]); ++ if (!probe_ent2) { ++ kfree(probe_ent); ++ return NULL; ++ } ++ ++ probe_ent->n_ports = 1; ++ probe_ent->irq = 14; + +- probe_ent[0].n_ports = 1; +- probe_ent[0].irq = 14; ++ probe_ent->hard_port_no = 0; ++ probe_ent->legacy_mode = 1; + +- probe_ent[0].hard_port_no = 0; +- probe_ent[0].legacy_mode = 1; ++ probe_ent2->n_ports = 1; ++ probe_ent2->irq = 15; + +- probe_ent[1].n_ports = 1; +- probe_ent[1].irq = 15; ++ probe_ent2->hard_port_no = 1; ++ probe_ent2->legacy_mode = 1; + +- probe_ent[1].hard_port_no = 1; +- probe_ent[1].legacy_mode = 1; +- +- probe_ent[0].port[0].cmd_addr = 0x1f0; +- probe_ent[0].port[0].altstatus_addr = +- probe_ent[0].port[0].ctl_addr = 0x3f6; +- probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4); +- +- probe_ent[1].port[0].cmd_addr = 0x170; +- probe_ent[1].port[0].altstatus_addr = +- probe_ent[1].port[0].ctl_addr = 0x376; +- probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8; ++ probe_ent->port[0].cmd_addr = 0x1f0; ++ probe_ent->port[0].altstatus_addr = ++ probe_ent->port[0].ctl_addr = 0x3f6; ++ probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); ++ ++ probe_ent2->port[0].cmd_addr = 0x170; ++ probe_ent2->port[0].altstatus_addr = ++ probe_ent2->port[0].ctl_addr = 0x376; ++ probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8; + +- ata_std_ports(&probe_ent[0].port[0]); +- ata_std_ports(&probe_ent[1].port[0]); ++ ata_std_ports(&probe_ent->port[0]); ++ ata_std_ports(&probe_ent2->port[0]); + ++ *ppe2 = probe_ent2; + return probe_ent; + } + +@@ -3587,6 +3749,7 @@ + struct ata_port_info *port[2]; + u8 tmp8, mask; + unsigned int legacy_mode = 0; ++ int disable_dev_on_err = 1; + int rc; + + DPRINTK("ENTER\n"); +@@ -3597,7 +3760,8 @@ + else + port[1] = port[0]; + +- if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) { ++ if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0 ++ && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + /* TODO: support transitioning to native mode? */ + pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); + mask = (1 << 2) | (1 << 0); +@@ -3616,18 +3780,22 @@ + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ disable_dev_on_err = 0; + goto err_out; ++ } + + if (legacy_mode) { +- if (!request_region(0x1f0, 8, "libata")) ++ if (!request_region(0x1f0, 8, "libata")) { ++ disable_dev_on_err = 0; + printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); +- else ++ } else + legacy_mode |= (1 << 0); + +- if (!request_region(0x170, 8, "libata")) ++ if (!request_region(0x170, 8, "libata")) { ++ disable_dev_on_err = 0; + printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); +- else ++ } else + legacy_mode |= (1 << 1); + } + +@@ -3642,9 +3810,7 @@ + goto err_out_regions; + + if (legacy_mode) { +- probe_ent = ata_pci_init_legacy_mode(pdev, port); +- if (probe_ent) +- probe_ent2 = &probe_ent[1]; ++ probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2); + } else + probe_ent = ata_pci_init_native_mode(pdev, port); + if (!probe_ent) { +@@ -3656,17 +3822,14 @@ + + spin_lock(&ata_module_lock); + if (legacy_mode) { +- int free = 0; + if (legacy_mode & (1 << 0)) + list_add_tail(&probe_ent->node, &ata_probe_list); + else +- free++; ++ kfree(probe_ent); + if (legacy_mode & (1 << 1)) + list_add_tail(&probe_ent2->node, &ata_probe_list); + else +- free++; +- if (free > 1) +- kfree(probe_ent); ++ kfree(probe_ent2); + } else { + list_add_tail(&probe_ent->node, &ata_probe_list); + } +@@ -3681,7 +3844,8 @@ + release_region(0x170, 8); + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (disable_dev_on_err) ++ pci_disable_device(pdev); + return rc; + } + +@@ -3723,15 +3887,12 @@ + if (host_set->mmio_base) + iounmap(host_set->mmio_base); + +- pci_release_regions(pdev); +- + for (i = 0; i < host_set->n_ports; i++) { +- struct ata_ioports *ioaddr; +- + ap = host_set->ports[i]; +- ioaddr = &ap->ioaddr; + + if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) { ++ struct ata_ioports *ioaddr = &ap->ioaddr; ++ + if (ioaddr->cmd_addr == 0x1f0) + release_region(0x1f0, 8); + else if (ioaddr->cmd_addr == 0x170) +@@ -3740,6 +3901,8 @@ + } + + kfree(host_set); ++ ++ pci_release_regions(pdev); + pci_disable_device(pdev); + dev_set_drvdata(dev, NULL); + } +@@ -3839,6 +4002,8 @@ + EXPORT_SYMBOL_GPL(ata_tf_to_fis); + EXPORT_SYMBOL_GPL(ata_tf_from_fis); + EXPORT_SYMBOL_GPL(ata_check_status); ++EXPORT_SYMBOL_GPL(ata_altstatus); ++EXPORT_SYMBOL_GPL(ata_chk_err); + EXPORT_SYMBOL_GPL(ata_exec_command); + EXPORT_SYMBOL_GPL(ata_port_start); + EXPORT_SYMBOL_GPL(ata_port_stop); +@@ -3847,6 +4012,8 @@ + EXPORT_SYMBOL_GPL(ata_bmdma_setup); + EXPORT_SYMBOL_GPL(ata_bmdma_start); + EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); ++EXPORT_SYMBOL_GPL(ata_bmdma_status); ++EXPORT_SYMBOL_GPL(ata_bmdma_stop); + EXPORT_SYMBOL_GPL(ata_port_probe); + EXPORT_SYMBOL_GPL(sata_phy_reset); + EXPORT_SYMBOL_GPL(__sata_phy_reset); +@@ -3857,7 +4024,6 @@ + EXPORT_SYMBOL_GPL(ata_scsi_error); + EXPORT_SYMBOL_GPL(ata_scsi_detect); + EXPORT_SYMBOL_GPL(ata_add_to_probe_list); +-EXPORT_SYMBOL_GPL(libata_msleep); + EXPORT_SYMBOL_GPL(ssleep); + EXPORT_SYMBOL_GPL(ata_scsi_release); + EXPORT_SYMBOL_GPL(ata_host_intr); +@@ -3867,7 +4033,6 @@ + + #ifdef CONFIG_PCI + EXPORT_SYMBOL_GPL(pci_test_config_bits); +-EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode); + EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); + EXPORT_SYMBOL_GPL(ata_pci_init_one); + EXPORT_SYMBOL_GPL(ata_pci_remove_one); +diff -Nur linux-2.4.29/drivers/scsi/libata.h linux-mips/drivers/scsi/libata.h +--- linux-2.4.29/drivers/scsi/libata.h 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/libata.h 2005-03-26 11:47:32.487319825 +0100 +@@ -37,6 +37,7 @@ + /* libata-core.c */ + extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, + struct ata_device *dev); ++extern void ata_qc_free(struct ata_queued_cmd *qc); + extern int ata_qc_issue(struct ata_queued_cmd *qc); + extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); + extern void ata_dev_select(struct ata_port *ap, unsigned int device, +diff -Nur linux-2.4.29/drivers/scsi/libata-scsi.c linux-mips/drivers/scsi/libata-scsi.c +--- linux-2.4.29/drivers/scsi/libata-scsi.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/libata-scsi.c 2005-03-26 11:47:32.485320153 +0100 +@@ -203,7 +203,7 @@ + {0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error + /* BBD - block marked bad */ + {0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error +- {0xFF, 0xFF, 0xFF, 0xFF}, // END mark ++ {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + }; + static unsigned char stat_table[][4] = { + /* Must be first because BUSY means no other bits valid */ +@@ -211,22 +211,22 @@ + {0x20, HARDWARE_ERROR, 0x00, 0x00}, // Device fault + {0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now + {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered +- {0xFF, 0xFF, 0xFF, 0xFF}, // END mark ++ {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + }; + int i = 0; + + cmd->result = SAM_STAT_CHECK_CONDITION; +- ++ + /* + * Is this an error we can process/parse + */ +- ++ + if(drv_stat & ATA_ERR) + /* Read the err bits */ + err = ata_chk_err(qc->ap); + + /* Display the ATA level error info */ +- ++ + printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat); + if(drv_stat & 0x80) + { +@@ -243,7 +243,7 @@ + if(drv_stat & 0x01) printk("Error "); + } + printk("}\n"); +- ++ + if(err) + { + printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err); +@@ -260,11 +260,11 @@ + if(err & 0x02) printk("TrackZeroNotFound "); + if(err & 0x01) printk("AddrMarkNotFound "); + printk("}\n"); +- ++ + /* Should we dump sector info here too ?? */ + } +- +- ++ ++ + /* Look for err */ + while(sense_table[i][0] != 0xFF) + { +@@ -283,7 +283,8 @@ + /* No immediate match */ + if(err) + printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err); +- ++ ++ i = 0; + /* Fall back to interpreting status bits */ + while(stat_table[i][0] != 0xFF) + { +@@ -301,7 +302,7 @@ + /* No error ?? */ + printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat); + /* additional-sense-code[-qualifier] */ +- ++ + sb[0] = 0x70; + sb[2] = MEDIUM_ERROR; + sb[7] = 0x0A; +@@ -449,19 +450,24 @@ + } + + if (lba48) { ++ tf->command = ATA_CMD_VERIFY_EXT; ++ + tf->hob_nsect = (n_sect >> 8) & 0xff; + + tf->hob_lbah = (sect >> 40) & 0xff; + tf->hob_lbam = (sect >> 32) & 0xff; + tf->hob_lbal = (sect >> 24) & 0xff; +- } else ++ } else { ++ tf->command = ATA_CMD_VERIFY; ++ + tf->device |= (sect >> 24) & 0xf; ++ } + + tf->nsect = n_sect & 0xff; + +- tf->hob_lbah = (sect >> 16) & 0xff; +- tf->hob_lbam = (sect >> 8) & 0xff; +- tf->hob_lbal = sect & 0xff; ++ tf->lbah = (sect >> 16) & 0xff; ++ tf->lbam = (sect >> 8) & 0xff; ++ tf->lbal = sect & 0xff; + + return 0; + } +@@ -561,7 +567,7 @@ + return 1; + + /* stores LBA27:24 in lower 4 bits of device reg */ +- tf->device |= scsicmd[2]; ++ tf->device |= scsicmd[6]; + + qc->nsect = scsicmd[13]; + } +@@ -657,6 +663,7 @@ + return; + + err_out: ++ ata_qc_free(qc); + ata_bad_cdb(cmd, done); + DPRINTK("EXIT - badcmd\n"); + } +diff -Nur linux-2.4.29/drivers/scsi/Makefile linux-mips/drivers/scsi/Makefile +--- linux-2.4.29/drivers/scsi/Makefile 2005-01-19 15:09:59.000000000 +0100 ++++ linux-mips/drivers/scsi/Makefile 2005-03-26 11:47:32.445326717 +0100 +@@ -134,6 +134,7 @@ + obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o + obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o + obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o ++obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o + obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o + obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o + obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o +diff -Nur linux-2.4.29/drivers/scsi/megaraid2.c linux-mips/drivers/scsi/megaraid2.c +--- linux-2.4.29/drivers/scsi/megaraid2.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/scsi/megaraid2.c 2005-03-26 11:47:33.007234495 +0100 +@@ -14,7 +14,7 @@ + * - speed-ups (list handling fixes, issued_list, optimizations.) + * - lots of cleanups. + * +- * Version : v2.10.3 (Apr 08, 2004) ++ * Version : v2.10.8.2 (July 26, 2004) + * + * Authors: Atul Mukker <Atul.Mukker@lsil.com> + * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com> +@@ -46,7 +46,7 @@ + + #include "megaraid2.h" + +-#ifdef LSI_CONFIG_COMPAT ++#if defined(__x86_64__) + #include <asm/ioctl32.h> + #endif + +@@ -90,10 +90,15 @@ + static struct mega_hbas mega_hbas[MAX_CONTROLLERS]; + + /* ++ * Lock to protect access to IOCTL ++ */ ++static struct semaphore megaraid_ioc_mtx; ++ ++/* + * The File Operations structure for the serial/ioctl interface of the driver + */ + static struct file_operations megadev_fops = { +- .ioctl = megadev_ioctl, ++ .ioctl = megadev_ioctl_entry, + .open = megadev_open, + .release = megadev_close, + .owner = THIS_MODULE, +@@ -107,7 +112,7 @@ + static struct mcontroller mcontroller[MAX_CONTROLLERS]; + + /* The current driver version */ +-static u32 driver_ver = 0x02100000; ++static u32 driver_ver = 0x02104000; + + /* major number used by the device for character interface */ + static int major; +@@ -189,6 +194,11 @@ + */ + mega_reorder_hosts(); + ++ /* ++ * Initialize the IOCTL lock ++ */ ++ init_MUTEX( &megaraid_ioc_mtx ); ++ + #ifdef CONFIG_PROC_FS + mega_proc_dir_entry = proc_mkdir("megaraid", &proc_root); + +@@ -223,7 +233,7 @@ + "MegaRAID Shutdown routine not registered!!\n"); + } + +-#ifdef LSI_CONFIG_COMPAT ++#if defined(__x86_64__) + /* + * Register the 32-bit ioctl conversion + */ +@@ -273,6 +283,8 @@ + unsigned long tbase; + unsigned long flag = 0; + int i, j; ++ u8 did_int_pthru_f = 0; ++ u8 did_int_data_f = 0; + + while((pdev = pci_find_device(pci_vendor, pci_device, pdev))) { + +@@ -328,6 +340,7 @@ + (subsysvid != HP_SUBSYS_VID) && + (subsysvid != INTEL_SUBSYS_VID) && + (subsysvid != FSC_SUBSYS_VID) && ++ (subsysvid != ACER_SUBSYS_VID) && + (subsysvid != LSI_SUBSYS_VID) ) continue; + + +@@ -465,6 +478,33 @@ + + alloc_scb_f = 1; + ++ /* ++ * Allocate memory for ioctls ++ */ ++ adapter->int_pthru = pci_alloc_consistent ( ++ adapter->dev, ++ sizeof(mega_passthru), ++ &adapter->int_pthru_dma_hndl ); ++ ++ if( adapter->int_pthru == NULL ) { ++ printk(KERN_WARNING "megaraid: out of RAM.\n"); ++ goto fail_attach; ++ } ++ else ++ did_int_pthru_f = 1; ++ ++ adapter->int_data = pci_alloc_consistent ( ++ adapter->dev, ++ INT_MEMBLK_SZ, ++ &adapter->int_data_dma_hndl ); ++ ++ if( adapter->int_data == NULL ) { ++ printk(KERN_WARNING "megaraid: out of RAM.\n"); ++ goto fail_attach; ++ } ++ else ++ did_int_data_f = 1; ++ + /* Request our IRQ */ + if( adapter->flag & BOARD_MEMMAP ) { + if(request_irq(irq, megaraid_isr_memmapped, SA_SHIRQ, +@@ -676,6 +716,19 @@ + continue; + + fail_attach: ++ if( did_int_data_f ) { ++ pci_free_consistent( ++ adapter->dev, INT_MEMBLK_SZ, adapter->int_data, ++ adapter->int_data_dma_hndl ); ++ } ++ ++ if( did_int_pthru_f ) { ++ pci_free_consistent( ++ adapter->dev, sizeof(mega_passthru), ++ (void*) adapter->int_pthru, ++ adapter->int_pthru_dma_hndl ); ++ } ++ + if( did_setup_mbox_f ) { + pci_free_consistent(adapter->dev, sizeof(mbox64_t), + (void *)adapter->una_mbox64, +@@ -937,6 +990,78 @@ + + + /** ++ * issue_scb() ++ * @adapter - pointer to our soft state ++ * @scb - scsi control block ++ * ++ * Post a command to the card if the mailbox is available, otherwise return ++ * busy. We also take the scb from the pending list if the mailbox is ++ * available. ++ */ ++static inline int ++issue_scb(adapter_t *adapter, scb_t *scb) ++{ ++ volatile mbox64_t *mbox64 = adapter->mbox64; ++ volatile mbox_t *mbox = adapter->mbox; ++ unsigned int i = 0; ++ ++ if(unlikely(mbox->busy)) { ++ do { ++ udelay(1); ++ i++; ++ } while( mbox->busy && (i < max_mbox_busy_wait) ); ++ ++ if(mbox->busy) return -1; ++ } ++ ++ /* Copy mailbox data into host structure */ ++ memcpy((char *)mbox, (char *)scb->raw_mbox, 16); ++ ++ mbox->cmdid = scb->idx; /* Set cmdid */ ++ mbox->busy = 1; /* Set busy */ ++ ++ ++ /* ++ * Increment the pending queue counter ++ */ ++ atomic_inc(&adapter->pend_cmds); ++ ++ switch (mbox->cmd) { ++ case MEGA_MBOXCMD_EXTPTHRU: ++ if( !adapter->has_64bit_addr ) break; ++ // else fall through ++ case MEGA_MBOXCMD_LREAD64: ++ case MEGA_MBOXCMD_LWRITE64: ++ case MEGA_MBOXCMD_PASSTHRU64: ++ mbox64->xfer_segment_lo = mbox->xferaddr; ++ mbox64->xfer_segment_hi = 0; ++ mbox->xferaddr = 0xFFFFFFFF; ++ break; ++ default: ++ mbox64->xfer_segment_lo = 0; ++ mbox64->xfer_segment_hi = 0; ++ } ++ ++ /* ++ * post the command ++ */ ++ scb->state |= SCB_ISSUED; ++ ++ if( likely(adapter->flag & BOARD_MEMMAP) ) { ++ mbox->poll = 0; ++ mbox->ack = 0; ++ WRINDOOR(adapter, adapter->mbox_dma | 0x1); ++ } ++ else { ++ irq_enable(adapter); ++ issue_command(adapter); ++ } ++ ++ return 0; ++} ++ ++ ++/** + * mega_runpendq() + * @adapter - pointer to our soft state + * +@@ -949,52 +1074,26 @@ + __mega_runpendq(adapter); + } + +-/* +- * megaraid_queue() +- * @scmd - Issue this scsi command +- * @done - the callback hook into the scsi mid-layer +- * +- * The command queuing entry point for the mid-layer. +- */ +-static int +-megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *)) +-{ +- adapter_t *adapter; +- scb_t *scb; +- int busy=0; +- +- adapter = (adapter_t *)scmd->host->hostdata; +- +- scmd->scsi_done = done; + ++static void ++__mega_runpendq(adapter_t *adapter) ++{ ++ scb_t *scb; ++ struct list_head *pos, *next; + +- /* +- * Allocate and build a SCB request +- * busy flag will be set if mega_build_cmd() command could not +- * allocate scb. We will return non-zero status in that case. +- * NOTE: scb can be null even though certain commands completed +- * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, we would +- * return 0 in that case. +- */ ++ /* Issue any pending commands to the card */ ++ list_for_each_safe(pos, next, &adapter->pending_list) { + +- scb = mega_build_cmd(adapter, scmd, &busy); ++ scb = list_entry(pos, scb_t, list); + +- if(scb) { +- scb->state |= SCB_PENDQ; +- list_add_tail(&scb->list, &adapter->pending_list); ++ if( !(scb->state & SCB_ISSUED) ) { + +- /* +- * Check if the HBA is in quiescent state, e.g., during a +- * delete logical drive opertion. If it is, don't run +- * the pending_list. +- */ +- if(atomic_read(&adapter->quiescent) == 0) { +- mega_runpendq(adapter); ++ if( issue_scb(adapter, scb) != 0 ) ++ return; + } +- return 0; + } + +- return busy; ++ return; + } + + +@@ -1068,25 +1167,136 @@ + } + + /* +- * If "delete logical drive" feature is enabled on this controller. +- * Do only if at least one delete logical drive operation was done. +- * +- * Also, after logical drive deletion, instead of logical drive number, ++ * If "delete logical drive" feature is enabled on this controller, + * the value returned should be 0x80+logical drive id. +- * +- * These is valid only for IO commands. + */ ++ if (adapter->support_random_del) ++ ldrv_num += 0x80; + +- if (adapter->support_random_del && adapter->read_ldidmap ) +- switch (cmd->cmnd[0]) { +- case READ_6: /* fall through */ +- case WRITE_6: /* fall through */ +- case READ_10: /* fall through */ +- case WRITE_10: +- ldrv_num += 0x80; ++ return ldrv_num; ++} ++ ++/* ++ * Wait until the controller's mailbox is available ++ */ ++static inline int ++mega_busywait_mbox (adapter_t *adapter) ++{ ++ if (adapter->mbox->busy) ++ return __mega_busywait_mbox(adapter); ++ return 0; ++} ++ ++ ++/** ++ * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs ++ * @adapter - controller's soft state ++ * ++ * Interrupt ackrowledgement sequence for IO mapped HBAs ++ */ ++static inline void ++megaraid_iombox_ack_sequence(adapter_t *adapter) ++{ ++ u8 status; ++ u8 nstatus; ++ u8 completed[MAX_FIRMWARE_STATUS]; ++ u8 byte; ++ int i; ++ ++ ++ /* ++ * loop till F/W has more commands for us to complete. ++ */ ++ do { ++ /* Check if a valid interrupt is pending */ ++ byte = irq_state(adapter); ++ if( (byte & VALID_INTR_BYTE) == 0 ) { ++ return; + } ++ set_irq_state(adapter, byte); + +- return ldrv_num; ++ while ((nstatus = adapter->mbox->numstatus) == 0xFF) { ++ cpu_relax(); ++ } ++ adapter->mbox->numstatus = 0xFF; ++ ++ for (i = 0; i < nstatus; i++) { ++ while ((completed[i] = adapter->mbox->completed[i]) ++ == 0xFF) { ++ cpu_relax(); ++ } ++ ++ adapter->mbox->completed[i] = 0xFF; ++ } ++ ++ // we must read the valid status now ++ if ((status = adapter->mbox->status) == 0xFF) { ++ printk(KERN_WARNING ++ "megaraid critical: status 0xFF from firmware.\n"); ++ } ++ adapter->mbox->status = 0xFF; ++ ++ /* ++ * decrement the pending queue counter ++ */ ++ atomic_sub(nstatus, &adapter->pend_cmds); ++ ++ /* Acknowledge interrupt */ ++ irq_ack(adapter); ++ ++ mega_cmd_done(adapter, completed, nstatus, status); ++ ++ } while(1); ++} ++ ++ ++ ++/* ++ * megaraid_queue() ++ * @scmd - Issue this scsi command ++ * @done - the callback hook into the scsi mid-layer ++ * ++ * The command queuing entry point for the mid-layer. ++ */ ++static int ++megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *)) ++{ ++ adapter_t *adapter; ++ scb_t *scb; ++ int busy=0; ++ ++ adapter = (adapter_t *)scmd->host->hostdata; ++ ++ scmd->scsi_done = done; ++ ++ ++ /* ++ * Allocate and build a SCB request ++ * busy flag will be set if mega_build_cmd() command could not ++ * allocate scb. We will return non-zero status in that case. ++ * NOTE: scb can be null even though certain commands completed ++ * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, we would ++ * return 0 in that case. ++ */ ++ ++ scb = mega_build_cmd(adapter, scmd, &busy); ++ ++ if(scb) { ++ scb->state |= SCB_PENDQ; ++ list_add_tail(&scb->list, &adapter->pending_list); ++ ++ /* ++ * Check if the HBA is in quiescent state, e.g., during a ++ * delete logical drive opertion. If it is, don't run ++ * the pending_list. ++ */ ++ if(atomic_read(&adapter->quiescent) == 0) { ++ mega_runpendq(adapter); ++ } ++ return 0; ++ } ++ ++ return busy; + } + + +@@ -1112,7 +1322,6 @@ + mbox_t *mbox; + long seg; + char islogical; +- int max_ldrv_num; + int channel = 0; + int target = 0; + int ldrv_num = 0; /* logical drive number */ +@@ -1184,24 +1393,6 @@ + } + + ldrv_num = mega_get_ldrv_num(adapter, cmd, channel); +- +- +- max_ldrv_num = (adapter->flag & BOARD_40LD) ? +- MAX_LOGICAL_DRIVES_40LD : MAX_LOGICAL_DRIVES_8LD; +- +- /* +- * max_ldrv_num increases by 0x80 if some logical drive was +- * deleted. +- */ +- if(adapter->read_ldidmap) +- max_ldrv_num += 0x80; +- +- if(ldrv_num > max_ldrv_num ) { +- cmd->result = (DID_BAD_TARGET << 16); +- cmd->scsi_done(cmd); +- return NULL; +- } +- + } + else { + if( cmd->lun > 7) { +@@ -1671,111 +1862,6 @@ + } + + +-static void +-__mega_runpendq(adapter_t *adapter) +-{ +- scb_t *scb; +- struct list_head *pos, *next; +- +- /* Issue any pending commands to the card */ +- list_for_each_safe(pos, next, &adapter->pending_list) { +- +- scb = list_entry(pos, scb_t, list); +- +- if( !(scb->state & SCB_ISSUED) ) { +- +- if( issue_scb(adapter, scb) != 0 ) +- return; +- } +- } +- +- return; +-} +- +- +-/** +- * issue_scb() +- * @adapter - pointer to our soft state +- * @scb - scsi control block +- * +- * Post a command to the card if the mailbox is available, otherwise return +- * busy. We also take the scb from the pending list if the mailbox is +- * available. +- */ +-static int +-issue_scb(adapter_t *adapter, scb_t *scb) +-{ +- volatile mbox64_t *mbox64 = adapter->mbox64; +- volatile mbox_t *mbox = adapter->mbox; +- unsigned int i = 0; +- +- if(unlikely(mbox->busy)) { +- do { +- udelay(1); +- i++; +- } while( mbox->busy && (i < max_mbox_busy_wait) ); +- +- if(mbox->busy) return -1; +- } +- +- /* Copy mailbox data into host structure */ +- memcpy((char *)mbox, (char *)scb->raw_mbox, 16); +- +- mbox->cmdid = scb->idx; /* Set cmdid */ +- mbox->busy = 1; /* Set busy */ +- +- +- /* +- * Increment the pending queue counter +- */ +- atomic_inc(&adapter->pend_cmds); +- +- switch (mbox->cmd) { +- case MEGA_MBOXCMD_EXTPTHRU: +- if( !adapter->has_64bit_addr ) break; +- // else fall through +- case MEGA_MBOXCMD_LREAD64: +- case MEGA_MBOXCMD_LWRITE64: +- case MEGA_MBOXCMD_PASSTHRU64: +- mbox64->xfer_segment_lo = mbox->xferaddr; +- mbox64->xfer_segment_hi = 0; +- mbox->xferaddr = 0xFFFFFFFF; +- break; +- default: +- mbox64->xfer_segment_lo = 0; +- mbox64->xfer_segment_hi = 0; +- } +- +- /* +- * post the command +- */ +- scb->state |= SCB_ISSUED; +- +- if( likely(adapter->flag & BOARD_MEMMAP) ) { +- mbox->poll = 0; +- mbox->ack = 0; +- WRINDOOR(adapter, adapter->mbox_dma | 0x1); +- } +- else { +- irq_enable(adapter); +- issue_command(adapter); +- } +- +- return 0; +-} +- +- +-/* +- * Wait until the controller's mailbox is available +- */ +-static inline int +-mega_busywait_mbox (adapter_t *adapter) +-{ +- if (adapter->mbox->busy) +- return __mega_busywait_mbox(adapter); +- return 0; +-} +- + /** + * issue_scb_block() + * @adapter - pointer to our soft state +@@ -1865,77 +1951,47 @@ + // invalidate the completed command id array. After command + // completion, firmware would write the valid id. + for (i = 0; i < MAX_FIRMWARE_STATUS; i++) { +- mbox->completed[i] = 0xFF; +- } +- +- return status; +- +-bug_blocked_mailbox: +- printk(KERN_WARNING "megaraid: Blocked mailbox......!!\n"); +- udelay (1000); +- return -1; +-} +- +- +-/** +- * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs +- * @adapter - controller's soft state +- * +- * Interrupt ackrowledgement sequence for IO mapped HBAs +- */ +-static inline void +-megaraid_iombox_ack_sequence(adapter_t *adapter) +-{ +- u8 status; +- u8 nstatus; +- u8 completed[MAX_FIRMWARE_STATUS]; +- u8 byte; +- int i; +- +- +- /* +- * loop till F/W has more commands for us to complete. +- */ +- do { +- /* Check if a valid interrupt is pending */ +- byte = irq_state(adapter); +- if( (byte & VALID_INTR_BYTE) == 0 ) { +- return; +- } +- set_irq_state(adapter, byte); ++ mbox->completed[i] = 0xFF; ++ } + +- while ((nstatus = adapter->mbox->numstatus) == 0xFF) { +- cpu_relax(); +- } +- adapter->mbox->numstatus = 0xFF; ++ return status; + +- for (i = 0; i < nstatus; i++) { +- while ((completed[i] = adapter->mbox->completed[i]) +- == 0xFF) { +- cpu_relax(); +- } ++bug_blocked_mailbox: ++ printk(KERN_WARNING "megaraid: Blocked mailbox......!!\n"); ++ udelay (1000); ++ return -1; ++} + +- adapter->mbox->completed[i] = 0xFF; +- } + +- // we must read the valid status now +- if ((status = adapter->mbox->status) == 0xFF) { +- printk(KERN_WARNING +- "megaraid critical: status 0xFF from firmware.\n"); +- } +- adapter->mbox->status = 0xFF; ++/** ++ * megaraid_isr_iomapped() ++ * @irq - irq ++ * @devp - pointer to our soft state ++ * @regs - unused ++ * ++ * Interrupt service routine for io-mapped controllers. ++ * Find out if our device is interrupting. If yes, acknowledge the interrupt ++ * and service the completed commands. ++ */ ++static void ++megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs) ++{ ++ adapter_t *adapter = devp; ++ unsigned long flags; + +- /* +- * decrement the pending queue counter +- */ +- atomic_sub(nstatus, &adapter->pend_cmds); + +- /* Acknowledge interrupt */ +- irq_ack(adapter); ++ spin_lock_irqsave(adapter->host_lock, flags); + +- mega_cmd_done(adapter, completed, nstatus, status); ++ megaraid_iombox_ack_sequence(adapter); + +- } while(1); ++ /* Loop through any pending requests */ ++ if( atomic_read(&adapter->quiescent ) == 0) { ++ mega_runpendq(adapter); ++ } ++ ++ spin_unlock_irqrestore(adapter->host_lock, flags); ++ ++ return; + } + + +@@ -2007,38 +2063,6 @@ + + + /** +- * megaraid_isr_iomapped() +- * @irq - irq +- * @devp - pointer to our soft state +- * @regs - unused +- * +- * Interrupt service routine for io-mapped controllers. +- * Find out if our device is interrupting. If yes, acknowledge the interrupt +- * and service the completed commands. +- */ +-static void +-megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs) +-{ +- adapter_t *adapter = devp; +- unsigned long flags; +- +- +- spin_lock_irqsave(adapter->host_lock, flags); +- +- megaraid_iombox_ack_sequence(adapter); +- +- /* Loop through any pending requests */ +- if( atomic_read(&adapter->quiescent ) == 0) { +- mega_runpendq(adapter); +- } +- +- spin_unlock_irqrestore(adapter->host_lock, flags); +- +- return; +-} +- +- +-/** + * megaraid_isr_memmapped() + * @irq - irq + * @devp - pointer to our soft state +@@ -2069,7 +2093,6 @@ + return; + } + +- + /** + * mega_cmd_done() + * @adapter - pointer to our soft state +@@ -2381,7 +2404,6 @@ + list_add(&scb->list, &adapter->free_list); + } + +- + static int + __mega_busywait_mbox (adapter_t *adapter) + { +@@ -2412,6 +2434,10 @@ + + cmd = scb->cmd; + ++ /* return 0 elements if no data transfer */ ++ if (!cmd->request_buffer || !cmd->request_bufflen) ++ return 0; ++ + /* Scatter-gather not used */ + if( !cmd->use_sg ) { + +@@ -2535,7 +2561,6 @@ + enquiry3->pdrv_state[i] = inquiry->pdrv_info.pdrv_state[i]; + } + +- + static inline void + mega_free_sgl(adapter_t *adapter) + { +@@ -2666,6 +2691,13 @@ + pci_free_consistent(adapter->dev, sizeof(mbox64_t), + (void *)adapter->una_mbox64, adapter->una_mbox64_dma); + ++ pci_free_consistent( adapter->dev, sizeof(mega_passthru), ++ (void*) adapter->int_pthru, ++ adapter->int_pthru_dma_hndl ); ++ ++ pci_free_consistent( adapter->dev, INT_MEMBLK_SZ, adapter->int_data, ++ adapter->int_data_dma_hndl ); ++ + hba_count--; + + if( hba_count == 0 ) { +@@ -2694,7 +2726,7 @@ + */ + scsi_unregister(host); + +-#ifdef LSI_CONFIG_COMPAT ++#if defined(__x86_64__) + unregister_ioctl32_conversion(MEGAIOCCMD); + #endif + +@@ -2736,30 +2768,36 @@ + } + + +-/** +- * megaraid_abort - abort the scsi command +- * @scp - command to be aborted +- * +- * Abort a previous SCSI request. Only commands on the pending list can be +- * aborted. All the commands issued to the F/W must complete. +- */ + static int + megaraid_abort(Scsi_Cmnd *scp) + { + adapter_t *adapter; + struct list_head *pos, *next; + scb_t *scb; +- long iter; +- int rval = SUCCESS; ++ ++ printk("megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n", ++ scp->serial_number, scp->cmnd[0], scp->channel, ++ scp->target, scp->lun); + + adapter = (adapter_t *)scp->host->hostdata; + +- ASSERT( spin_is_locked(adapter->host_lock) ); ++ /* ++ * Check if hw_error flag was set in previous RESET call. If it was, ++ * then FW is hanging and unlikely to function. We can return FAILURE ++ * from here and expect the RESET handler to be called. ++ */ + +- printk("megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n", +- scp->serial_number, scp->cmnd[0], scp->channel, scp->target, +- scp->lun); ++ if (adapter->hw_error) { ++ printk("megaraid: hw error, cannot abort\n"); ++ return FAILED; ++ } ++ ++ ASSERT( spin_is_locked(adapter->host_lock) ); + ++ /* ++ * If cmd is waiting to be issued to FW, ABORT it with SUCEESS. If it ++ * has already been issued, return FAILURE and expect RESET later. ++ */ + + list_for_each_safe( pos, next, &adapter->pending_list ) { + +@@ -2769,15 +2807,11 @@ + + scb->state |= SCB_ABORT; + +- /* +- * Check if this command was never issued. If this is +- * the case, take it off from the pending list and +- * complete. +- */ + if( !(scb->state & SCB_ISSUED) ) { + +- printk(KERN_WARNING +- "megaraid: %ld:%d, driver owner.\n", ++ /* Not issued to the FW yet; ABORT it */ ++ ++ printk( "megaraid: %ld:%d, driver owner.\n", + scp->serial_number, scb->idx); + + scp->result = (DID_ABORT << 16); +@@ -2786,67 +2820,31 @@ + + scp->scsi_done(scp); + +- break; ++ return SUCCESS; ++ } ++ else { ++ /* Issued to the FW; can do nothing */ ++ return FAILED; + } + } + } + + /* +- * By this time, either all commands are completed or aborted by +- * mid-layer. Do not return until all the commands are actually +- * completed by the firmware ++ * cmd is _not_ in our pending_list. Most likely we completed the cmd + */ +- iter = 0; +- while( atomic_read(&adapter->pend_cmds) > 0 ) { +- /* +- * Perform the ack sequence, since interrupts are not +- * available right now! +- */ +- if( adapter->flag & BOARD_MEMMAP ) { +- megaraid_memmbox_ack_sequence(adapter); +- } +- else { +- megaraid_iombox_ack_sequence(adapter); +- } +- +- /* +- * print a message once every second only +- */ +- if( !(iter % 1000) ) { +- printk( +- "megaraid: Waiting for %d commands to flush: iter:%ld\n", +- atomic_read(&adapter->pend_cmds), iter); +- } +- +- if( iter++ < MBOX_ABORT_SLEEP*1000 ) { +- mdelay(1); +- } +- else { +- printk(KERN_WARNING +- "megaraid: critical hardware error!\n"); +- +- rval = FAILED; +- +- break; +- } +- } +- +- if( rval == SUCCESS ) { +- printk(KERN_INFO +- "megaraid: abort sequence successfully completed.\n"); +- } +- +- return rval; ++ return SUCCESS; + } + + + static int + megaraid_reset(Scsi_Cmnd *cmd) + { +- adapter_t *adapter; +- megacmd_t mc; +- long iter; +- int rval = SUCCESS; ++ DECLARE_WAIT_QUEUE_HEAD(wq); ++ int i; ++ scb_t *scb; ++ adapter_t *adapter; ++ struct list_head *pos, *next; ++ int rval; + + adapter = (adapter_t *)cmd->host->hostdata; + +@@ -2856,31 +2854,54 @@ + cmd->serial_number, cmd->cmnd[0], cmd->channel, cmd->target, + cmd->lun); + ++ /* ++ * Check if hw_error flag was set in previous RESET call. If it was, ++ * then we needn't do any handling here. The controller will be marked ++ * offline soon ++ */ + +-#if MEGA_HAVE_CLUSTERING +- mc.cmd = MEGA_CLUSTER_CMD; +- mc.opcode = MEGA_RESET_RESERVATIONS; +- +- spin_unlock_irq(adapter->host_lock); +- if( mega_internal_command(adapter, LOCK_INT, &mc, NULL) != 0 ) { +- printk(KERN_WARNING +- "megaraid: reservation reset failed.\n"); ++ if (adapter->hw_error) { ++ printk("megaraid: hw error, cannot reset\n"); ++ return FAILED; + } +- else { +- printk(KERN_INFO "megaraid: reservation reset.\n"); ++ ++ /* ++ * Return all the pending cmds to the mid-layer with the cmd result ++ * DID_RESET. Make sure you don't return the cmds ISSUED to FW. ++ */ ++ list_for_each_safe( pos, next, &adapter->pending_list ) { ++ ++ scb = list_entry(pos, scb_t, list); ++ scb->state |= SCB_RESET; ++ ++ if( !(scb->state & SCB_ISSUED) ) { ++ ++ /* Not issued to the FW; return with RESET */ ++ cmd->result = (DID_RESET << 16); ++ ++ mega_free_scb(adapter, scb); ++ cmd->scsi_done(cmd); ++ } + } +- spin_lock_irq(adapter->host_lock); +-#endif + + /* +- * Do not return until all the commands are actually completed by the +- * firmware ++ * Under exceptional conditions, FW may take up to 3 mins to complete ++ * processing all pending commands. We'll wait for maximum 3 mins to ++ * see if all outstanding commands are completed. + */ +- iter = 0; +- while( atomic_read(&adapter->pend_cmds) > 0 ) { ++ ++ if (atomic_read(&adapter->pend_cmds) == 0) ++ return SUCCESS; ++ ++ printk("megaraid: %d pending cmds; max wait %d seconds\n", ++ atomic_read(&adapter->pend_cmds), MBOX_RESET_WAIT ); ++ ++ for(i=0; (i<MBOX_RESET_WAIT)&&(atomic_read(&adapter->pend_cmds)); i++){ ++ ++ ASSERT( spin_is_locked(adapter->host_lock) ); ++ + /* +- * Perform the ack sequence, since interrupts are not +- * available right now! ++ * Perform the ack sequence, since interrupts are unavailable + */ + if( adapter->flag & BOARD_MEMMAP ) { + megaraid_memmbox_ack_sequence(adapter); +@@ -2889,55 +2910,35 @@ + megaraid_iombox_ack_sequence(adapter); + } + +- /* +- * print a message once every second only +- */ +- if( !(iter % 1000) ) { +- printk( +- "megaraid: Waiting for %d commands to flush: iter:%ld\n", +- atomic_read(&adapter->pend_cmds), iter); +- } ++ spin_unlock(adapter->host_lock); + +- if( iter++ < MBOX_RESET_SLEEP*1000 ) { +- mdelay(1); ++ /* Print a message once every 5 seconds */ ++ if (!(i % 5)) { ++ printk("megaraid: pending %d; remaining %d seconds\n", ++ atomic_read(&adapter->pend_cmds), ++ MBOX_RESET_WAIT - i); + } +- else { +- printk(KERN_WARNING +- "megaraid: critical hardware error!\n"); + +- rval = FAILED; +- +- break; +- } +- } ++ sleep_on_timeout(&wq, HZ); + +- if( rval == SUCCESS ) { +- printk(KERN_INFO +- "megaraid: reset sequence successfully completed.\n"); ++ spin_lock(adapter->host_lock); + } + +- return rval; +-} +- ++ /* ++ * If after 3 mins there are still outstanding cmds, set the hw_error ++ * flag so that we can return from subsequent ABORT/RESET handlers ++ * without any processing ++ */ + +-/** +- * mega_allocate_inquiry() +- * @dma_handle - handle returned for dma address +- * @pdev - handle to pci device +- * +- * allocates memory for inquiry structure +- */ +-static inline caddr_t +-mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev) +-{ +- return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle); +-} ++ rval = SUCCESS; ++ if (atomic_read(&adapter->pend_cmds)) { + ++ adapter->hw_error = 1; ++ printk("megaraid: critical hardware error!\n" ); ++ rval = FAILED; ++ } + +-static inline void +-mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev) +-{ +- pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle); ++ return rval; + } + + +@@ -3199,6 +3200,26 @@ + return len; + } + ++/** ++ * mega_allocate_inquiry() ++ * @dma_handle - handle returned for dma address ++ * @pdev - handle to pci device ++ * ++ * allocates memory for inquiry structure ++ */ ++static inline caddr_t ++mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev) ++{ ++ return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle); ++} ++ ++ ++static inline void ++mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev) ++{ ++ pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle); ++} ++ + + /** + * proc_rebuild_rate() +@@ -3988,6 +4009,7 @@ + megaraid_reboot_notify (struct notifier_block *this, unsigned long code, + void *unused) + { ++ DECLARE_WAIT_QUEUE_HEAD(wq); + adapter_t *adapter; + struct Scsi_Host *host; + u8 raw_mbox[sizeof(mbox_t)]; +@@ -4040,10 +4062,10 @@ + printk(KERN_INFO "megaraid: cache flush delay: "); + for( i = 9; i >= 0; i-- ) { + printk("\b\b\b[%d]", i); +- mdelay(1000); ++ sleep_on_timeout(&wq, HZ); + } + printk("\b\b\b[done]\n"); +- mdelay(1000); ++ sleep_on_timeout(&wq, HZ); + + return NOTIFY_DONE; + } +@@ -4150,17 +4172,27 @@ + } + + +-#ifdef LSI_CONFIG_COMPAT ++#if defined(__x86_64__) + static int + megadev_compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, + struct file *filep) + { + struct inode *inode = filep->f_dentry->d_inode; + +- return megadev_ioctl(inode, filep, cmd, arg); ++ return megadev_ioctl_entry(inode, filep, cmd, arg); + } + #endif + ++static int ++megadev_ioctl_entry(struct inode *inode, struct file *filep, unsigned int cmd, ++ unsigned long arg) ++{ ++ int rval; ++ down( &megaraid_ioc_mtx ); ++ rval = megadev_ioctl( inode, filep, cmd, arg ); ++ up( &megaraid_ioc_mtx ); ++ return rval; ++} + + /** + * megadev_ioctl() +@@ -4184,9 +4216,8 @@ + int rval; + mega_passthru *upthru; /* user address for passthru */ + mega_passthru *pthru; /* copy user passthru here */ +- dma_addr_t pthru_dma_hndl; + void *data = NULL; /* data to be transferred */ +- dma_addr_t data_dma_hndl; /* dma handle for data xfer area */ ++ dma_addr_t data_dma_hndl = 0; + megacmd_t mc; + megastat_t *ustats; + int num_ldrv; +@@ -4302,7 +4333,7 @@ + /* + * Which adapter + */ +- if( (adapno = GETADAP(uioc.adapno)) >= hba_count ) ++ if( (adapno = GETADAP(uioc.adapno)) >= hba_count ) + return (-ENODEV); + + adapter = hba_soft_state[adapno]; +@@ -4358,13 +4389,7 @@ + if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU ) { + /* Passthru commands */ + +- pthru = pci_alloc_consistent(pdev, +- sizeof(mega_passthru), +- &pthru_dma_hndl); +- +- if( pthru == NULL ) { +- return (-ENOMEM); +- } ++ pthru = adapter->int_pthru; + + /* + * The user passthru structure +@@ -4376,29 +4401,27 @@ + */ + if( copy_from_user(pthru, (char *)upthru, + sizeof(mega_passthru)) ) { +- +- pci_free_consistent(pdev, +- sizeof(mega_passthru), pthru, +- pthru_dma_hndl); +- + return (-EFAULT); + } + + /* +- * Is there a data transfer ++ * Is there a data transfer; If the data transfer ++ * length is <= INT_MEMBLK_SZ, usr the buffer ++ * allocated at the load time. Otherwise, allocate it ++ * here. + */ +- if( pthru->dataxferlen ) { +- data = pci_alloc_consistent(pdev, +- pthru->dataxferlen, +- &data_dma_hndl); +- +- if( data == NULL ) { +- pci_free_consistent(pdev, +- sizeof(mega_passthru), +- pthru, +- pthru_dma_hndl); ++ if (pthru->dataxferlen) { ++ if (pthru->dataxferlen > INT_MEMBLK_SZ) { ++ data = pci_alloc_consistent ( ++ pdev, ++ pthru->dataxferlen, ++ &data_dma_hndl ); + +- return (-ENOMEM); ++ if (data == NULL) ++ return (-ENOMEM); ++ } ++ else { ++ data = adapter->int_data; + } + + /* +@@ -4406,7 +4429,11 @@ + * address at just allocated memory + */ + uxferaddr = pthru->dataxferaddr; +- pthru->dataxferaddr = data_dma_hndl; ++ if (data_dma_hndl) ++ pthru->dataxferaddr = data_dma_hndl; ++ else ++ pthru->dataxferaddr = ++ adapter->int_data_dma_hndl; + } + + +@@ -4421,14 +4448,14 @@ + (char *)((ulong)uxferaddr), + pthru->dataxferlen) ) { + rval = (-EFAULT); +- goto freemem_and_return; ++ goto freedata_and_return; + } + } + + memset(&mc, 0, sizeof(megacmd_t)); + + mc.cmd = MEGA_MBOXCMD_PASSTHRU; +- mc.xferaddr = (u32)pthru_dma_hndl; ++ mc.xferaddr = (u32)adapter->int_pthru_dma_hndl; + + /* + * Issue the command +@@ -4437,7 +4464,7 @@ + + rval = mega_n_to_m((void *)arg, &mc); + +- if( rval ) goto freemem_and_return; ++ if( rval ) goto freedata_and_return; + + + /* +@@ -4456,18 +4483,14 @@ + */ + copy_to_user(upthru->reqsensearea, + pthru->reqsensearea, 14); +- +-freemem_and_return: +- if( pthru->dataxferlen ) { +- pci_free_consistent(pdev, +- pthru->dataxferlen, data, +- data_dma_hndl); ++freedata_and_return: ++ if (data_dma_hndl) { ++ pci_free_consistent( pdev, pthru->dataxferlen, ++ data, data_dma_hndl ); + } + +- pci_free_consistent(pdev, sizeof(mega_passthru), +- pthru, pthru_dma_hndl); +- + return rval; ++ + } + else { + /* DCMD commands */ +@@ -4476,13 +4499,18 @@ + * Is there a data transfer + */ + if( uioc.xferlen ) { +- data = pci_alloc_consistent(pdev, +- uioc.xferlen, &data_dma_hndl); ++ if (uioc.xferlen > INT_MEMBLK_SZ) { ++ data = pci_alloc_consistent( ++ pdev, ++ uioc.xferlen, ++ &data_dma_hndl ); + +- if( data == NULL ) { +- return (-ENOMEM); ++ if (data == NULL) ++ return (-ENOMEM); ++ } ++ else { ++ data = adapter->int_data; + } +- + uxferaddr = MBOX(uioc)->xferaddr; + } + +@@ -4497,9 +4525,9 @@ + (char *)((ulong)uxferaddr), + uioc.xferlen) ) { + +- pci_free_consistent(pdev, +- uioc.xferlen, data, +- data_dma_hndl); ++ pci_free_consistent( ++ pdev, uioc.xferlen, ++ data, data_dma_hndl ); + + return (-EFAULT); + } +@@ -4507,7 +4535,10 @@ + + memcpy(&mc, MBOX(uioc), sizeof(megacmd_t)); + +- mc.xferaddr = (u32)data_dma_hndl; ++ if (data_dma_hndl ) ++ mc.xferaddr = (u32)data_dma_hndl; ++ else ++ mc.xferaddr = (u32)(adapter->int_data_dma_hndl); + + /* + * Issue the command +@@ -4517,12 +4548,10 @@ + rval = mega_n_to_m((void *)arg, &mc); + + if( rval ) { +- if( uioc.xferlen ) { +- pci_free_consistent(pdev, +- uioc.xferlen, data, +- data_dma_hndl); ++ if (data_dma_hndl) { ++ pci_free_consistent( pdev, uioc.xferlen, ++ data, data_dma_hndl ); + } +- + return rval; + } + +@@ -4537,10 +4566,9 @@ + } + } + +- if( uioc.xferlen ) { +- pci_free_consistent(pdev, +- uioc.xferlen, data, +- data_dma_hndl); ++ if (data_dma_hndl) { ++ pci_free_consistent( pdev, uioc.xferlen, ++ data, data_dma_hndl ); + } + + return rval; +@@ -4725,19 +4753,22 @@ + else { + uioc_mimd = (struct uioctl_t *)arg; + +- if( put_user(mc->status, (u8 *)&uioc_mimd->mbox[17]) ) ++ if( put_user(mc->status, (u8 *)&uioc_mimd->mbox[17]) ) { + return (-EFAULT); ++ } + + if( mc->cmd == MEGA_MBOXCMD_PASSTHRU ) { + + umc = (megacmd_t *)uioc_mimd->mbox; +- if (copy_from_user(&kmc, umc, sizeof(megacmd_t))) ++ if (copy_from_user(&kmc, umc, sizeof(megacmd_t))) { + return -EFAULT; ++ } + + upthru = (mega_passthru *)((ulong)kmc.xferaddr); + +- if( put_user(mc->status, (u8 *)&upthru->scsistatus) ) ++ if( put_user(mc->status, (u8 *)&upthru->scsistatus) ){ + return (-EFAULT); ++ } + } + } + +@@ -5148,7 +5179,6 @@ + } + + +- + /** + * mega_reorder_hosts() + * +@@ -5363,6 +5393,7 @@ + } + + ++ + /** mega_internal_dev_inquiry() + * @adapter - pointer to our soft state + * @ch - channel for this device +diff -Nur linux-2.4.29/drivers/scsi/megaraid2.h linux-mips/drivers/scsi/megaraid2.h +--- linux-2.4.29/drivers/scsi/megaraid2.h 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/scsi/megaraid2.h 2005-03-26 11:47:33.143212178 +0100 +@@ -6,7 +6,7 @@ + + + #define MEGARAID_VERSION \ +- "v2.10.3 (Release Date: Thu Apr 8 16:16:05 EDT 2004)\n" ++ "v2.10.8.2 (Release Date: Mon Jul 26 12:15:51 EDT 2004)\n" + + /* + * Driver features - change the values to enable or disable features in the +@@ -82,6 +82,7 @@ + #define LSI_SUBSYS_VID 0x1000 + #define INTEL_SUBSYS_VID 0x8086 + #define FSC_SUBSYS_VID 0x1734 ++#define ACER_SUBSYS_VID 0x1025 + + #define HBA_SIGNATURE 0x3344 + #define HBA_SIGNATURE_471 0xCCCC +@@ -978,6 +979,15 @@ + cmds */ + + int has_cluster; /* cluster support on this HBA */ ++ ++#define INT_MEMBLK_SZ (28*1024) ++ mega_passthru *int_pthru; /*internal pthru*/ ++ dma_addr_t int_pthru_dma_hndl; ++ caddr_t int_data; /*internal data*/ ++ dma_addr_t int_data_dma_hndl; ++ ++ int hw_error; ++ + }adapter_t; + + +@@ -1085,18 +1095,21 @@ + + #define MBOX_ABORT_SLEEP 60 + #define MBOX_RESET_SLEEP 30 ++#define MBOX_RESET_WAIT 180 + + const char *megaraid_info (struct Scsi_Host *); + + static int megaraid_detect(Scsi_Host_Template *); + static void mega_find_card(Scsi_Host_Template *, u16, u16); + static int mega_query_adapter(adapter_t *); +-static int issue_scb(adapter_t *, scb_t *); ++static inline int issue_scb(adapter_t *, scb_t *); + static int mega_setup_mailbox(adapter_t *); + + static int megaraid_queue (Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); + static scb_t * mega_build_cmd(adapter_t *, Scsi_Cmnd *, int *); ++static inline scb_t *mega_allocate_scb(adapter_t *, Scsi_Cmnd *); + static void __mega_runpendq(adapter_t *); ++static inline void mega_runpendq(adapter_t *); + static int issue_scb_block(adapter_t *, u_char *); + + static void megaraid_isr_memmapped(int, void *, struct pt_regs *); +@@ -1113,6 +1126,7 @@ + + static int mega_build_sglist (adapter_t *adapter, scb_t *scb, + u32 *buffer, u32 *length); ++static inline int mega_busywait_mbox (adapter_t *); + static int __mega_busywait_mbox (adapter_t *); + static void mega_cmd_done(adapter_t *, u8 [], int, int); + static inline void mega_free_sgl (adapter_t *adapter); +@@ -1123,15 +1137,13 @@ + unsigned long, void *); + static int megadev_open (struct inode *, struct file *); + +-#if defined(CONFIG_COMPAT) || defined( __x86_64__) || defined(IA32_EMULATION) +-#define LSI_CONFIG_COMPAT +-#endif +- +-#ifdef LSI_CONFIG_COMPAT ++#if defined(__x86_64__) + static int megadev_compat_ioctl(unsigned int, unsigned int, unsigned long, + struct file *); + #endif + ++static int megadev_ioctl_entry (struct inode *, struct file *, unsigned int, ++ unsigned long); + static int megadev_ioctl (struct inode *, struct file *, unsigned int, + unsigned long); + static int mega_m_to_n(void *, nitioctl_t *); +@@ -1164,6 +1176,8 @@ + + static int mega_adapinq(adapter_t *, dma_addr_t); + static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t); ++static inline caddr_t mega_allocate_inquiry(dma_addr_t *, struct pci_dev *); ++static inline void mega_free_inquiry(caddr_t, dma_addr_t, struct pci_dev *); + static int mega_print_inquiry(char *, char *); + #endif + +@@ -1174,6 +1188,7 @@ + scb_t *, Scsi_Cmnd *, int, int); + static void mega_enum_raid_scsi(adapter_t *); + static void mega_get_boot_drv(adapter_t *); ++static inline int mega_get_ldrv_num(adapter_t *, Scsi_Cmnd *, int); + static int mega_support_random_del(adapter_t *); + static int mega_del_logdrv(adapter_t *, int); + static int mega_do_del_logdrv(adapter_t *, int); diff -Nur linux-2.4.29/drivers/scsi/NCR53C9x.h linux-mips/drivers/scsi/NCR53C9x.h --- linux-2.4.29/drivers/scsi/NCR53C9x.h 2004-02-18 14:36:31.000000000 +0100 +++ linux-mips/drivers/scsi/NCR53C9x.h 2003-12-15 19:19:51.000000000 +0100 @@ -17286,9 +26093,1697 @@ diff -Nur linux-2.4.29/drivers/scsi/NCR53C9x.h linux-mips/drivers/scsi/NCR53C9x. #define esp_read(__reg) (__reg) struct ESP_regs { +diff -Nur linux-2.4.29/drivers/scsi/osst.c linux-mips/drivers/scsi/osst.c +--- linux-2.4.29/drivers/scsi/osst.c 2004-08-08 01:26:05.000000000 +0200 ++++ linux-mips/drivers/scsi/osst.c 2005-03-26 11:47:33.149211193 +0100 +@@ -5505,7 +5505,6 @@ + read: osst_read, + write: osst_write, + ioctl: osst_ioctl, +- llseek: no_llseek, + open: os_scsi_tape_open, + flush: os_scsi_tape_flush, + release: os_scsi_tape_close, +diff -Nur linux-2.4.29/drivers/scsi/sata_nv.c linux-mips/drivers/scsi/sata_nv.c +--- linux-2.4.29/drivers/scsi/sata_nv.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_nv.c 2005-03-26 11:47:33.156210045 +0100 +@@ -20,6 +20,10 @@ + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * ++ * 0.06 ++ * - Added generic SATA support by using a pci_device_id that filters on ++ * the IDE storage class code. ++ * + * 0.03 + * - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using + * mmio_base, which is only set for the CK804/MCP04 case. +@@ -44,7 +48,7 @@ + #include <linux/libata.h> + + #define DRV_NAME "sata_nv" +-#define DRV_VERSION "0.5" ++#define DRV_VERSION "0.6" + + #define NV_PORTS 2 + #define NV_PIO_MASK 0x1f +@@ -95,7 +99,8 @@ + #define NV_MCP_SATA_CFG_20_SATA_SPACE_EN 0x04 + + static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +-irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs); ++static irqreturn_t nv_interrupt (int irq, void *dev_instance, ++ struct pt_regs *regs); + static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); + static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); + static void nv_host_stop (struct ata_host_set *host_set); +@@ -108,6 +113,7 @@ + + enum nv_host_type + { ++ GENERIC, + NFORCE2, + NFORCE3, + CK804 +@@ -128,6 +134,9 @@ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 }, ++ { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, ++ PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, + { 0, } /* terminate list */ + }; + +@@ -136,7 +145,6 @@ + struct nv_host_desc + { + enum nv_host_type host_type; +- unsigned long host_flags; + void (*enable_hotplug)(struct ata_probe_ent *probe_ent); + void (*disable_hotplug)(struct ata_host_set *host_set); + void (*check_hotplug)(struct ata_host_set *host_set); +@@ -144,21 +152,24 @@ + }; + static struct nv_host_desc nv_device_tbl[] = { + { ++ .host_type = GENERIC, ++ .enable_hotplug = NULL, ++ .disable_hotplug= NULL, ++ .check_hotplug = NULL, ++ }, ++ { + .host_type = NFORCE2, +- .host_flags = 0x00000000, + .enable_hotplug = nv_enable_hotplug, + .disable_hotplug= nv_disable_hotplug, + .check_hotplug = nv_check_hotplug, + }, + { + .host_type = NFORCE3, +- .host_flags = 0x00000000, + .enable_hotplug = nv_enable_hotplug, + .disable_hotplug= nv_disable_hotplug, + .check_hotplug = nv_check_hotplug, + }, + { .host_type = CK804, +- .host_flags = NV_HOST_FLAGS_SCR_MMIO, + .enable_hotplug = nv_enable_hotplug_ck804, + .disable_hotplug= nv_disable_hotplug_ck804, + .check_hotplug = nv_check_hotplug_ck804, +@@ -168,6 +179,7 @@ + struct nv_host + { + struct nv_host_desc *host_desc; ++ unsigned long host_flags; + }; + + static struct pci_driver nv_pci_driver = { +@@ -207,6 +219,8 @@ + .phy_reset = sata_phy_reset, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, +@@ -245,7 +259,8 @@ + MODULE_DEVICE_TABLE(pci, nv_pci_tbl); + MODULE_VERSION(DRV_VERSION); + +-irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs) ++static irqreturn_t nv_interrupt (int irq, void *dev_instance, ++ struct pt_regs *regs) + { + struct ata_host_set *host_set = dev_instance; + struct nv_host *host = host_set->private_data; +@@ -285,8 +300,8 @@ + if (sc_reg > SCR_CONTROL) + return 0xffffffffU; + +- if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) +- return readl(ap->ioaddr.scr_addr + (sc_reg * 4)); ++ if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) ++ return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4)); + else + return inl(ap->ioaddr.scr_addr + (sc_reg * 4)); + } +@@ -299,8 +314,8 @@ + if (sc_reg > SCR_CONTROL) + return; + +- if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) +- writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); ++ if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) ++ writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4)); + else + outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + } +@@ -322,7 +337,16 @@ + struct nv_host *host; + struct ata_port_info *ppi; + struct ata_probe_ent *probe_ent; ++ int pci_dev_busy = 0; + int rc; ++ u32 bar; ++ ++ // Make sure this is a SATA controller by counting the number of bars ++ // (NVIDIA SATA controllers will always have six bars). Otherwise, ++ // it's an IDE controller and we ignore it. ++ for (bar=0; bar<6; bar++) ++ if (pci_resource_start(pdev, bar) == 0) ++ return -ENODEV; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); +@@ -332,8 +356,10 @@ + goto err_out; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out_disable; ++ } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) +@@ -350,11 +376,15 @@ + if (!host) + goto err_out_free_ent; + ++ memset(host, 0, sizeof(struct nv_host)); + host->host_desc = &nv_device_tbl[ent->driver_data]; + + probe_ent->private_data = host; + +- if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) { ++ if (pci_resource_flags(pdev, 5) & IORESOURCE_MEM) ++ host->host_flags |= NV_HOST_FLAGS_SCR_MMIO; ++ ++ if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) { + unsigned long base; + + probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5), +@@ -395,7 +425,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out_disable: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + err_out: + return rc; + } +diff -Nur linux-2.4.29/drivers/scsi/sata_promise.c linux-mips/drivers/scsi/sata_promise.c +--- linux-2.4.29/drivers/scsi/sata_promise.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_promise.c 2005-03-26 11:47:33.159209552 +0100 +@@ -42,8 +42,6 @@ + #define DRV_NAME "sata_promise" + #define DRV_VERSION "1.01" + +-#define msleep libata_msleep /* 2.4-specific */ +- + enum { + PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ + PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ +@@ -158,10 +156,18 @@ + board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, ++ { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ board_2037x }, ++ { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ board_2037x }, ++ + { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20319 }, + { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20319 }, ++ { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ board_20319 }, ++ + { } /* terminate list */ + }; + +@@ -408,9 +414,11 @@ + return IRQ_NONE; + } + +- spin_lock(&host_set->lock); ++ spin_lock(&host_set->lock); ++ ++ writel(mask, mmio_base + PDC_INT_SEQMASK); + +- for (i = 0; i < host_set->n_ports; i++) { ++ for (i = 0; i < host_set->n_ports; i++) { + VPRINTK("port %u\n", i); + ap = host_set->ports[i]; + tmp = mask & (1 << (i + 1)); +@@ -548,6 +556,7 @@ + unsigned long base; + void *mmio_base; + unsigned int board_idx = (unsigned int) ent->driver_data; ++ int pci_dev_busy = 0; + int rc; + + if (!printed_version++) +@@ -562,8 +571,10 @@ + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) +@@ -637,7 +648,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + } + +diff -Nur linux-2.4.29/drivers/scsi/sata_qstor.c linux-mips/drivers/scsi/sata_qstor.c +--- linux-2.4.29/drivers/scsi/sata_qstor.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_qstor.c 2005-03-18 13:13:28.000000000 +0100 +@@ -0,0 +1,717 @@ ++/* ++ * sata_qstor.c - Pacific Digital Corporation QStor SATA ++ * ++ * Maintained by: Mark Lord <mlord@pobox.com> ++ * ++ * Copyright 2005 Pacific Digital Corporation. ++ * (OSL/GPL code release authorized by Jalil Fadavi). ++ * ++ * The contents of this file are subject to the Open ++ * Software License version 1.1 that can be found at ++ * http://www.opensource.org/licenses/osl-1.1.txt and is included herein ++ * by reference. ++ * ++ * Alternatively, the contents of this file may be used under the terms ++ * of the GNU General Public License version 2 (the "GPL") as distributed ++ * in the kernel source COPYING file, in which case the provisions of ++ * the GPL are applicable instead of the above. If you wish to allow ++ * the use of your version of this file only under the terms of the ++ * GPL and not to allow others to use your version of this file under ++ * the OSL, indicate your decision by deleting the provisions above and ++ * replace them with the notice and other provisions required by the GPL. ++ * If you do not delete the provisions above, a recipient may use your ++ * version of this file under either the OSL or the GPL. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/pci.h> ++#include <linux/init.h> ++#include <linux/blkdev.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/sched.h> ++#include "scsi.h" ++#include <scsi/scsi_host.h> ++#include <asm/io.h> ++#include <linux/libata.h> ++ ++#define DRV_NAME "sata_qstor" ++#define DRV_VERSION "0.04" ++ ++enum { ++ QS_PORTS = 4, ++ QS_MAX_PRD = LIBATA_MAX_PRD, ++ QS_CPB_ORDER = 6, ++ QS_CPB_BYTES = (1 << QS_CPB_ORDER), ++ QS_PRD_BYTES = QS_MAX_PRD * 16, ++ QS_PKT_BYTES = QS_CPB_BYTES + QS_PRD_BYTES, ++ ++ QS_DMA_BOUNDARY = ~0UL, ++ ++ /* global register offsets */ ++ QS_HCF_CNFG3 = 0x0003, /* host configuration offset */ ++ QS_HID_HPHY = 0x0004, /* host physical interface info */ ++ QS_HCT_CTRL = 0x00e4, /* global interrupt mask offset */ ++ QS_HST_SFF = 0x0100, /* host status fifo offset */ ++ QS_HVS_SERD3 = 0x0393, /* PHY enable offset */ ++ ++ /* global control bits */ ++ QS_HPHY_64BIT = (1 << 1), /* 64-bit bus detected */ ++ QS_CNFG3_GSRST = 0x01, /* global chip reset */ ++ QS_SERD3_PHY_ENA = 0xf0, /* PHY detection ENAble*/ ++ ++ /* per-channel register offsets */ ++ QS_CCF_CPBA = 0x0710, /* chan CPB base address */ ++ QS_CCF_CSEP = 0x0718, /* chan CPB separation factor */ ++ QS_CFC_HUFT = 0x0800, /* host upstream fifo threshold */ ++ QS_CFC_HDFT = 0x0804, /* host downstream fifo threshold */ ++ QS_CFC_DUFT = 0x0808, /* dev upstream fifo threshold */ ++ QS_CFC_DDFT = 0x080c, /* dev downstream fifo threshold */ ++ QS_CCT_CTR0 = 0x0900, /* chan control-0 offset */ ++ QS_CCT_CTR1 = 0x0901, /* chan control-1 offset */ ++ QS_CCT_CFF = 0x0a00, /* chan command fifo offset */ ++ ++ /* channel control bits */ ++ QS_CTR0_REG = (1 << 1), /* register mode (vs. pkt mode) */ ++ QS_CTR0_CLER = (1 << 2), /* clear channel errors */ ++ QS_CTR1_RDEV = (1 << 1), /* sata phy/comms reset */ ++ QS_CTR1_RCHN = (1 << 4), /* reset channel logic */ ++ QS_CCF_RUN_PKT = 0x107, /* RUN a new dma PKT */ ++ ++ /* pkt sub-field headers */ ++ QS_HCB_HDR = 0x01, /* Host Control Block header */ ++ QS_DCB_HDR = 0x02, /* Device Control Block header */ ++ ++ /* pkt HCB flag bits */ ++ QS_HF_DIRO = (1 << 0), /* data DIRection Out */ ++ QS_HF_DAT = (1 << 3), /* DATa pkt */ ++ QS_HF_IEN = (1 << 4), /* Interrupt ENable */ ++ QS_HF_VLD = (1 << 5), /* VaLiD pkt */ ++ ++ /* pkt DCB flag bits */ ++ QS_DF_PORD = (1 << 2), /* Pio OR Dma */ ++ QS_DF_ELBA = (1 << 3), /* Extended LBA (lba48) */ ++ ++ /* PCI device IDs */ ++ board_2068_idx = 0, /* QStor 4-port SATA/RAID */ ++}; ++ ++typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t; ++ ++struct qs_port_priv { ++ u8 *pkt; ++ dma_addr_t pkt_dma; ++ qs_state_t state; ++}; ++ ++static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg); ++static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); ++static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); ++static irqreturn_t qs_intr (int irq, void *dev_instance, struct pt_regs *regs); ++static int qs_port_start(struct ata_port *ap); ++static void qs_host_stop(struct ata_host_set *host_set); ++static void qs_port_stop(struct ata_port *ap); ++static void qs_phy_reset(struct ata_port *ap); ++static void qs_qc_prep(struct ata_queued_cmd *qc); ++static int qs_qc_issue(struct ata_queued_cmd *qc); ++static int qs_check_atapi_dma(struct ata_queued_cmd *qc); ++static void qs_bmdma_stop(struct ata_port *ap); ++static u8 qs_bmdma_status(struct ata_port *ap); ++static void qs_irq_clear(struct ata_port *ap); ++static void qs_eng_timeout(struct ata_port *ap); ++ ++static Scsi_Host_Template qs_ata_sht = { ++ .module = THIS_MODULE, ++ .name = DRV_NAME, ++ .detect = ata_scsi_detect, ++ .release = ata_scsi_release, ++ .ioctl = ata_scsi_ioctl, ++ .queuecommand = ata_scsi_queuecmd, ++ .eh_strategy_handler = ata_scsi_error, ++ .can_queue = ATA_DEF_QUEUE, ++ .this_id = ATA_SHT_THIS_ID, ++ .sg_tablesize = QS_MAX_PRD, ++ .max_sectors = ATA_MAX_SECTORS, ++ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, ++ .use_new_eh_code = ATA_SHT_NEW_EH_CODE, ++ .emulated = ATA_SHT_EMULATED, ++ //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING, ++ .use_clustering = ENABLE_CLUSTERING, ++ .proc_name = DRV_NAME, ++ .bios_param = ata_std_bios_param, ++}; ++ ++static struct ata_port_operations qs_ata_ops = { ++ .port_disable = ata_port_disable, ++ .tf_load = ata_tf_load, ++ .tf_read = ata_tf_read, ++ .check_status = ata_check_status, ++ .check_atapi_dma = qs_check_atapi_dma, ++ .exec_command = ata_exec_command, ++ .dev_select = ata_std_dev_select, ++ .phy_reset = qs_phy_reset, ++ .qc_prep = qs_qc_prep, ++ .qc_issue = qs_qc_issue, ++ .eng_timeout = qs_eng_timeout, ++ .irq_handler = qs_intr, ++ .irq_clear = qs_irq_clear, ++ .scr_read = qs_scr_read, ++ .scr_write = qs_scr_write, ++ .port_start = qs_port_start, ++ .port_stop = qs_port_stop, ++ .host_stop = qs_host_stop, ++ .bmdma_stop = qs_bmdma_stop, ++ .bmdma_status = qs_bmdma_status, ++}; ++ ++static struct ata_port_info qs_port_info[] = { ++ /* board_2068_idx */ ++ { ++ .sht = &qs_ata_sht, ++ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ++ ATA_FLAG_SATA_RESET | ++ //FIXME ATA_FLAG_SRST | ++ ATA_FLAG_MMIO, ++ .pio_mask = 0x10, /* pio4 */ ++ .udma_mask = 0x7f, /* udma0-6 */ ++ .port_ops = &qs_ata_ops, ++ }, ++}; ++ ++static struct pci_device_id qs_ata_pci_tbl[] = { ++ { PCI_VENDOR_ID_PDC, 0x2068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ board_2068_idx }, ++ ++ { } /* terminate list */ ++}; ++ ++static struct pci_driver qs_ata_pci_driver = { ++ .name = DRV_NAME, ++ .id_table = qs_ata_pci_tbl, ++ .probe = qs_ata_init_one, ++ .remove = ata_pci_remove_one, ++}; ++ ++static int qs_check_atapi_dma(struct ata_queued_cmd *qc) ++{ ++ return 1; /* ATAPI DMA not supported */ ++} ++ ++static void qs_bmdma_stop(struct ata_port *ap) ++{ ++ /* nothing */ ++} ++ ++static u8 qs_bmdma_status(struct ata_port *ap) ++{ ++ return 0; ++} ++ ++static void qs_irq_clear(struct ata_port *ap) ++{ ++ /* nothing */ ++} ++ ++static inline void qs_enter_reg_mode(struct ata_port *ap) ++{ ++ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000); ++ ++ writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); ++ readb(chan + QS_CCT_CTR0); /* flush */ ++} ++ ++static inline void qs_reset_channel_logic(struct ata_port *ap) ++{ ++ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000); ++ ++ writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1); ++ readb(chan + QS_CCT_CTR0); /* flush */ ++ qs_enter_reg_mode(ap); ++} ++ ++static void qs_phy_reset(struct ata_port *ap) ++{ ++ struct qs_port_priv *pp = ap->private_data; ++ ++ pp->state = qs_state_idle; ++ qs_reset_channel_logic(ap); ++ sata_phy_reset(ap); ++} ++ ++static void qs_eng_timeout(struct ata_port *ap) ++{ ++ struct qs_port_priv *pp = ap->private_data; ++ ++ if (pp->state != qs_state_idle) /* healthy paranoia */ ++ pp->state = qs_state_mmio; ++ qs_reset_channel_logic(ap); ++ ata_eng_timeout(ap); ++} ++ ++static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg) ++{ ++ if (sc_reg > SCR_CONTROL) ++ return ~0U; ++ return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); ++} ++ ++static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) ++{ ++ if (sc_reg > SCR_CONTROL) ++ return; ++ writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); ++} ++ ++static void qs_fill_sg(struct ata_queued_cmd *qc) ++{ ++ struct scatterlist *sg = qc->sg; ++ struct ata_port *ap = qc->ap; ++ struct qs_port_priv *pp = ap->private_data; ++ unsigned int nelem; ++ u8 *prd = pp->pkt + QS_CPB_BYTES; ++ ++ assert(sg != NULL); ++ assert(qc->n_elem > 0); ++ ++ for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) { ++ u64 addr; ++ u32 len; ++ ++ addr = sg_dma_address(sg); ++ *(__le64 *)prd = cpu_to_le64(addr); ++ prd += sizeof(u64); ++ ++ len = sg_dma_len(sg); ++ *(__le32 *)prd = cpu_to_le32(len); ++ prd += sizeof(u64); ++ ++ VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem, ++ (unsigned long long)addr, len); ++ } ++} ++ ++static void qs_qc_prep(struct ata_queued_cmd *qc) ++{ ++ struct qs_port_priv *pp = qc->ap->private_data; ++ u8 dflags = QS_DF_PORD, *buf = pp->pkt; ++ u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD; ++ u64 addr; ++ ++ VPRINTK("ENTER\n"); ++ ++ qs_enter_reg_mode(qc->ap); ++ if (qc->tf.protocol != ATA_PROT_DMA) { ++ ata_qc_prep(qc); ++ return; ++ } ++ ++ qs_fill_sg(qc); ++ ++ if ((qc->tf.flags & ATA_TFLAG_WRITE)) ++ hflags |= QS_HF_DIRO; ++ if ((qc->tf.flags & ATA_TFLAG_LBA48)) ++ dflags |= QS_DF_ELBA; ++ ++ /* host control block (HCB) */ ++ buf[ 0] = QS_HCB_HDR; ++ buf[ 1] = hflags; ++ *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE); ++ *(__le32 *)(&buf[ 8]) = cpu_to_le32(qc->n_elem); ++ addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES; ++ *(__le64 *)(&buf[16]) = cpu_to_le64(addr); ++ ++ /* device control block (DCB) */ ++ buf[24] = QS_DCB_HDR; ++ buf[28] = dflags; ++ ++ /* frame information structure (FIS) */ ++ ata_tf_to_fis(&qc->tf, &buf[32], 0); ++} ++ ++static inline void qs_packet_start(struct ata_queued_cmd *qc) ++{ ++ struct ata_port *ap = qc->ap; ++ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000); ++ ++ VPRINTK("ENTER, ap %p\n", ap); ++ ++ writeb(QS_CTR0_CLER, chan + QS_CCT_CTR0); ++ wmb(); /* flush PRDs and pkt to memory */ ++ writel(QS_CCF_RUN_PKT, chan + QS_CCT_CFF); ++ readl(chan + QS_CCT_CFF); /* flush */ ++} ++ ++static int qs_qc_issue(struct ata_queued_cmd *qc) ++{ ++ struct qs_port_priv *pp = qc->ap->private_data; ++ ++ switch (qc->tf.protocol) { ++ case ATA_PROT_DMA: ++ ++ pp->state = qs_state_pkt; ++ qs_packet_start(qc); ++ return 0; ++ ++ case ATA_PROT_ATAPI_DMA: ++ BUG(); ++ break; ++ ++ default: ++ break; ++ } ++ ++ pp->state = qs_state_mmio; ++ return ata_qc_issue_prot(qc); ++} ++ ++static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) ++{ ++ unsigned int handled = 0; ++ u8 sFFE; ++ u8 __iomem *mmio_base = host_set->mmio_base; ++ ++ do { ++ u32 sff0 = readl(mmio_base + QS_HST_SFF); ++ u32 sff1 = readl(mmio_base + QS_HST_SFF + 4); ++ u8 sEVLD = (sff1 >> 30) & 0x01; /* valid flag */ ++ sFFE = sff1 >> 31; /* empty flag */ ++ ++ if (sEVLD) { ++ u8 sDST = sff0 >> 16; /* dev status */ ++ u8 sHST = sff1 & 0x3f; /* host status */ ++ unsigned int port_no = (sff1 >> 8) & 0x03; ++ struct ata_port *ap = host_set->ports[port_no]; ++ ++ DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", ++ sff1, sff0, port_no, sHST, sDST); ++ handled = 1; ++ if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { ++ struct ata_queued_cmd *qc; ++ struct qs_port_priv *pp = ap->private_data; ++ if (!pp || pp->state != qs_state_pkt) ++ continue; ++ qc = ata_qc_from_tag(ap, ap->active_tag); ++ if (qc && (!(qc->tf.ctl & ATA_NIEN))) { ++ switch (sHST) { ++ case 0: /* sucessful CPB */ ++ case 3: /* device error */ ++ pp->state = qs_state_idle; ++ qs_enter_reg_mode(qc->ap); ++ ata_qc_complete(qc, sDST); ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ } ++ } while (!sFFE); ++ return handled; ++} ++ ++static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) ++{ ++ unsigned int handled = 0, port_no; ++ ++ for (port_no = 0; port_no < host_set->n_ports; ++port_no) { ++ struct ata_port *ap; ++ ap = host_set->ports[port_no]; ++ if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { ++ struct ata_queued_cmd *qc; ++ struct qs_port_priv *pp = ap->private_data; ++ if (!pp || pp->state != qs_state_mmio) ++ continue; ++ qc = ata_qc_from_tag(ap, ap->active_tag); ++ if (qc && (!(qc->tf.ctl & ATA_NIEN))) { ++ ++ /* check main status, clearing INTRQ */ ++ u8 status = ata_chk_status(ap); ++ if ((status & ATA_BUSY)) ++ continue; ++ DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", ++ ap->id, qc->tf.protocol, status); ++ ++ /* complete taskfile transaction */ ++ pp->state = qs_state_idle; ++ ata_qc_complete(qc, status); ++ handled = 1; ++ } ++ } ++ } ++ return handled; ++} ++ ++static irqreturn_t qs_intr(int irq, void *dev_instance, struct pt_regs *regs) ++{ ++ struct ata_host_set *host_set = dev_instance; ++ unsigned int handled = 0; ++ ++ VPRINTK("ENTER\n"); ++ ++ spin_lock(&host_set->lock); ++ handled = qs_intr_pkt(host_set) | qs_intr_mmio(host_set); ++ spin_unlock(&host_set->lock); ++ ++ VPRINTK("EXIT\n"); ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base) ++{ ++ port->cmd_addr = ++ port->data_addr = base + 0x400; ++ port->error_addr = ++ port->feature_addr = base + 0x408; /* hob_feature = 0x409 */ ++ port->nsect_addr = base + 0x410; /* hob_nsect = 0x411 */ ++ port->lbal_addr = base + 0x418; /* hob_lbal = 0x419 */ ++ port->lbam_addr = base + 0x420; /* hob_lbam = 0x421 */ ++ port->lbah_addr = base + 0x428; /* hob_lbah = 0x429 */ ++ port->device_addr = base + 0x430; ++ port->status_addr = ++ port->command_addr = base + 0x438; ++ port->altstatus_addr = ++ port->ctl_addr = base + 0x440; ++ port->scr_addr = base + 0xc00; ++} ++ ++static int qs_port_start(struct ata_port *ap) ++{ ++ struct device *dev = ap->host_set->dev; ++ struct qs_port_priv *pp; ++ void __iomem *mmio_base = ap->host_set->mmio_base; ++ void __iomem *chan = mmio_base + (ap->port_no * 0x4000); ++ u64 addr; ++ int rc; ++ ++ rc = ata_port_start(ap); ++ if (rc) ++ return rc; ++ qs_enter_reg_mode(ap); ++ pp = kcalloc(1, sizeof(*pp), GFP_KERNEL); ++ if (!pp) { ++ rc = -ENOMEM; ++ goto err_out; ++ } ++ pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma, ++ GFP_KERNEL); ++ if (!pp->pkt) { ++ rc = -ENOMEM; ++ goto err_out_kfree; ++ } ++ memset(pp->pkt, 0, QS_PKT_BYTES); ++ ap->private_data = pp; ++ ++ addr = (u64)pp->pkt_dma; ++ writel((u32) addr, chan + QS_CCF_CPBA); ++ writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4); ++ return 0; ++ ++err_out_kfree: ++ kfree(pp); ++err_out: ++ ata_port_stop(ap); ++ return rc; ++} ++ ++static void qs_port_stop(struct ata_port *ap) ++{ ++ struct device *dev = ap->host_set->dev; ++ struct qs_port_priv *pp = ap->private_data; ++ ++ if (pp != NULL) { ++ ap->private_data = NULL; ++ if (pp->pkt != NULL) ++ dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt, ++ pp->pkt_dma); ++ kfree(pp); ++ } ++ ata_port_stop(ap); ++} ++ ++static void qs_host_stop(struct ata_host_set *host_set) ++{ ++ void __iomem *mmio_base = host_set->mmio_base; ++ ++ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ ++ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */ ++} ++ ++static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe) ++{ ++ void __iomem *mmio_base = pe->mmio_base; ++ unsigned int port_no; ++ ++ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ ++ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */ ++ ++ /* reset each channel in turn */ ++ for (port_no = 0; port_no < pe->n_ports; ++port_no) { ++ u8 __iomem *chan = mmio_base + (port_no * 0x4000); ++ writeb(QS_CTR1_RDEV|QS_CTR1_RCHN, chan + QS_CCT_CTR1); ++ writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); ++ readb(chan + QS_CCT_CTR0); /* flush */ ++ } ++ writeb(QS_SERD3_PHY_ENA, mmio_base + QS_HVS_SERD3); /* enable phy */ ++ ++ for (port_no = 0; port_no < pe->n_ports; ++port_no) { ++ u8 __iomem *chan = mmio_base + (port_no * 0x4000); ++ /* set FIFO depths to same settings as Windows driver */ ++ writew(32, chan + QS_CFC_HUFT); ++ writew(32, chan + QS_CFC_HDFT); ++ writew(10, chan + QS_CFC_DUFT); ++ writew( 8, chan + QS_CFC_DDFT); ++ /* set CPB size in bytes, as a power of two */ ++ writeb(QS_CPB_ORDER, chan + QS_CCF_CSEP); ++ } ++ writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */ ++} ++ ++/* ++ * The QStor understands 64-bit buses, and uses 64-bit fields ++ * for DMA pointers regardless of bus width. We just have to ++ * make sure our DMA masks are set appropriately for whatever ++ * bridge lies between us and the QStor, and then the DMA mapping ++ * code will ensure we only ever "see" appropriate buffer addresses. ++ * If we're 32-bit limited somewhere, then our 64-bit fields will ++ * just end up with zeros in the upper 32-bits, without any special ++ * logic required outside of this routine (below). ++ */ ++static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) ++{ ++ u32 bus_info = readl(mmio_base + QS_HID_HPHY); ++ int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT); ++ ++ if (have_64bit_bus && ++ !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { ++ /* do nothing */ ++ } else { ++ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ if (rc) { ++ printk(KERN_ERR DRV_NAME ++ "(%s): 32-bit DMA enable failed\n", ++ pci_name(pdev)); ++ return rc; ++ } ++ } ++ return 0; ++} ++ ++static int qs_ata_init_one(struct pci_dev *pdev, ++ const struct pci_device_id *ent) ++{ ++ static int printed_version; ++ struct ata_probe_ent *probe_ent = NULL; ++ void __iomem *mmio_base; ++ unsigned int board_idx = (unsigned int) ent->driver_data; ++ int rc, port_no; ++ ++ if (!printed_version++) ++ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); ++ ++ rc = pci_enable_device(pdev); ++ if (rc) ++ return rc; ++ ++ rc = pci_request_regions(pdev, DRV_NAME); ++ if (rc) ++ goto err_out; ++ ++ if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) { ++ rc = -ENODEV; ++ goto err_out_regions; ++ } ++ ++ mmio_base = ioremap(pci_resource_start(pdev, 4), ++ pci_resource_len(pdev, 4)); ++ if (mmio_base == NULL) { ++ rc = -ENOMEM; ++ goto err_out_regions; ++ } ++ ++ rc = qs_set_dma_masks(pdev, mmio_base); ++ if (rc) ++ goto err_out_iounmap; ++ ++ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); ++ if (probe_ent == NULL) { ++ rc = -ENOMEM; ++ goto err_out_iounmap; ++ } ++ ++ memset(probe_ent, 0, sizeof(*probe_ent)); ++ probe_ent->dev = pci_dev_to_dev(pdev); ++ INIT_LIST_HEAD(&probe_ent->node); ++ ++ probe_ent->sht = qs_port_info[board_idx].sht; ++ probe_ent->host_flags = qs_port_info[board_idx].host_flags; ++ probe_ent->pio_mask = qs_port_info[board_idx].pio_mask; ++ probe_ent->mwdma_mask = qs_port_info[board_idx].mwdma_mask; ++ probe_ent->udma_mask = qs_port_info[board_idx].udma_mask; ++ probe_ent->port_ops = qs_port_info[board_idx].port_ops; ++ ++ probe_ent->irq = pdev->irq; ++ probe_ent->irq_flags = SA_SHIRQ; ++ probe_ent->mmio_base = mmio_base; ++ probe_ent->n_ports = QS_PORTS; ++ ++ for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) { ++ unsigned long chan = (unsigned long)mmio_base + ++ (port_no * 0x4000); ++ qs_ata_setup_port(&probe_ent->port[port_no], chan); ++ } ++ ++ pci_set_master(pdev); ++ ++ /* initialize adapter */ ++ qs_host_init(board_idx, probe_ent); ++ ++ ata_add_to_probe_list(probe_ent); ++ return 0; ++ ++err_out_iounmap: ++ iounmap(mmio_base); ++err_out_regions: ++ pci_release_regions(pdev); ++err_out: ++ pci_disable_device(pdev); ++ return rc; ++} ++ ++static int __init qs_ata_init(void) ++{ ++ int rc; ++ ++ rc = pci_module_init(&qs_ata_pci_driver); ++ if (rc) ++ return rc; ++ ++ rc = scsi_register_module(MODULE_SCSI_HA, &qs_ata_sht); ++ if (rc) { ++ rc = -ENODEV; ++ goto err_out; ++ } ++ ++ return 0; ++ ++err_out: ++ pci_unregister_driver(&qs_ata_pci_driver); ++ return rc; ++} ++ ++static void __exit qs_ata_exit(void) ++{ ++ scsi_unregister_module(MODULE_SCSI_HA, &qs_ata_sht); ++ pci_unregister_driver(&qs_ata_pci_driver); ++} ++ ++MODULE_AUTHOR("Mark Lord"); ++MODULE_DESCRIPTION("Pacific Digital Corporation QStor SATA low-level driver"); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(pci, qs_ata_pci_tbl); ++MODULE_VERSION(DRV_VERSION); ++ ++module_init(qs_ata_init); ++module_exit(qs_ata_exit); +diff -Nur linux-2.4.29/drivers/scsi/sata_sil.c linux-mips/drivers/scsi/sata_sil.c +--- linux-2.4.29/drivers/scsi/sata_sil.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_sil.c 2005-03-26 11:47:33.241196096 +0100 +@@ -71,12 +71,14 @@ + { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, ++ { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, ++ { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { } /* terminate list */ + }; + + + /* TODO firmware versions should be added - eric */ +-struct sil_drivelist { ++static const struct sil_drivelist { + const char * product; + unsigned int quirk; + } sil_blacklist [] = { +@@ -84,10 +86,12 @@ + { "ST330013AS", SIL_QUIRK_MOD15WRITE }, + { "ST340017AS", SIL_QUIRK_MOD15WRITE }, + { "ST360015AS", SIL_QUIRK_MOD15WRITE }, ++ { "ST380013AS", SIL_QUIRK_MOD15WRITE }, + { "ST380023AS", SIL_QUIRK_MOD15WRITE }, + { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, + { "ST3160023AS", SIL_QUIRK_MOD15WRITE }, + { "ST3120026AS", SIL_QUIRK_MOD15WRITE }, ++ { "ST3200822AS", SIL_QUIRK_MOD15WRITE }, + { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, + { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, + { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, +@@ -136,6 +140,8 @@ + .post_set_mode = sil_post_set_mode, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, +@@ -333,6 +339,7 @@ + void *mmio_base; + int rc; + unsigned int i; ++ int pci_dev_busy = 0; + u32 tmp, irq_mask; + + if (!printed_version++) +@@ -347,8 +354,10 @@ + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) +@@ -430,7 +439,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + } + +diff -Nur linux-2.4.29/drivers/scsi/sata_sis.c linux-mips/drivers/scsi/sata_sis.c +--- linux-2.4.29/drivers/scsi/sata_sis.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_sis.c 2005-03-26 11:47:33.244195604 +0100 +@@ -103,6 +103,8 @@ + .phy_reset = sata_phy_reset, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, +@@ -201,14 +203,17 @@ + int rc; + u32 genctl; + struct ata_port_info *ppi; ++ int pci_dev_busy = 0; + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) +@@ -255,7 +260,8 @@ + pci_release_regions(pdev); + + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + + } +diff -Nur linux-2.4.29/drivers/scsi/sata_svw.c linux-mips/drivers/scsi/sata_svw.c +--- linux-2.4.29/drivers/scsi/sata_svw.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_svw.c 2005-03-26 11:47:33.246195276 +0100 +@@ -156,7 +156,7 @@ + * spin_lock_irqsave(host_set lock) + */ + +-void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) ++static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) + { + struct ata_port *ap = qc->ap; + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); +@@ -186,7 +186,7 @@ + * spin_lock_irqsave(host_set lock) + */ + +-void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) ++static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) + { + struct ata_port *ap = qc->ap; + void *mmio = (void *) ap->ioaddr.bmdma_addr; +@@ -302,6 +302,8 @@ + .phy_reset = sata_phy_reset, + .bmdma_setup = k2_bmdma_setup_mmio, + .bmdma_start = k2_bmdma_start_mmio, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, +@@ -339,6 +341,7 @@ + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; + void *mmio_base; ++ int pci_dev_busy = 0; + int rc; + + if (!printed_version++) +@@ -360,8 +363,10 @@ + + /* Request PCI regions */ + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) +@@ -429,7 +434,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + } + +diff -Nur linux-2.4.29/drivers/scsi/sata_sx4.c linux-mips/drivers/scsi/sata_sx4.c +--- linux-2.4.29/drivers/scsi/sata_sx4.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_sx4.c 2005-03-26 11:47:33.249194784 +0100 +@@ -1191,8 +1191,7 @@ + error = 0; + break; + } +- set_current_state(TASK_UNINTERRUPTIBLE); +- schedule_timeout((i * 100) * HZ / 1000 + 1); ++ msleep(i*100); + } + return error; + } +@@ -1225,8 +1224,7 @@ + readl(mmio + PDC_TIME_CONTROL); + + /* Wait 3 seconds */ +- set_current_state(TASK_UNINTERRUPTIBLE); +- schedule_timeout(3 * HZ); ++ msleep(3000); + + /* + When timer is enabled, counter is decreased every internal +@@ -1369,6 +1367,7 @@ + void *mmio_base, *dimm_mmio = NULL; + struct pdc_host_priv *hpriv = NULL; + unsigned int board_idx = (unsigned int) ent->driver_data; ++ int pci_dev_busy = 0; + int rc; + + if (!printed_version++) +@@ -1383,8 +1382,10 @@ + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) +@@ -1469,7 +1470,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + } + +diff -Nur linux-2.4.29/drivers/scsi/sata_uli.c linux-mips/drivers/scsi/sata_uli.c +--- linux-2.4.29/drivers/scsi/sata_uli.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_uli.c 2005-03-26 11:47:33.252194291 +0100 +@@ -98,6 +98,8 @@ + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + +@@ -186,14 +188,17 @@ + struct ata_port_info *ppi; + int rc; + unsigned int board_idx = (unsigned int) ent->driver_data; ++ int pci_dev_busy = 0; + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) +@@ -256,7 +261,8 @@ + pci_release_regions(pdev); + + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + + } +diff -Nur linux-2.4.29/drivers/scsi/sata_via.c linux-mips/drivers/scsi/sata_via.c +--- linux-2.4.29/drivers/scsi/sata_via.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_via.c 2005-03-26 11:47:33.268191666 +0100 +@@ -24,6 +24,11 @@ + If you do not delete the provisions above, a recipient may use your + version of this file under either the OSL or the GPL. + ++ ---------------------------------------------------------------------- ++ ++ To-do list: ++ * VT6421 PATA support ++ + */ + + #include <linux/kernel.h> +@@ -38,11 +43,14 @@ + #include <asm/io.h> + + #define DRV_NAME "sata_via" +-#define DRV_VERSION "1.0" ++#define DRV_VERSION "1.1" + +-enum { +- via_sata = 0, ++enum board_ids_enum { ++ vt6420, ++ vt6421, ++}; + ++enum { + SATA_CHAN_ENAB = 0x40, /* SATA channel enable */ + SATA_INT_GATE = 0x41, /* SATA interrupt gating */ + SATA_NATIVE_MODE = 0x42, /* Native mode enable */ +@@ -50,10 +58,8 @@ + + PORT0 = (1 << 1), + PORT1 = (1 << 0), +- +- ENAB_ALL = PORT0 | PORT1, +- +- INT_GATE_ALL = PORT0 | PORT1, ++ ALL_PORTS = PORT0 | PORT1, ++ N_PORTS = 2, + + NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), + +@@ -66,7 +72,8 @@ + static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); + + static struct pci_device_id svia_pci_tbl[] = { +- { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, via_sata }, ++ { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 }, ++ { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 }, + + { } /* terminate list */ + }; +@@ -111,6 +118,9 @@ + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, ++ + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + +@@ -159,18 +169,132 @@ + 8, 4, 8, 4, 16, 256 + }; + ++static const unsigned int vt6421_bar_sizes[] = { ++ 16, 16, 16, 16, 32, 128 ++}; ++ + static unsigned long svia_scr_addr(unsigned long addr, unsigned int port) + { + return addr + (port * 128); + } + ++static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port) ++{ ++ return addr + (port * 64); ++} ++ ++static void vt6421_init_addrs(struct ata_probe_ent *probe_ent, ++ struct pci_dev *pdev, ++ unsigned int port) ++{ ++ unsigned long reg_addr = pci_resource_start(pdev, port); ++ unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8); ++ unsigned long scr_addr; ++ ++ probe_ent->port[port].cmd_addr = reg_addr; ++ probe_ent->port[port].altstatus_addr = ++ probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS; ++ probe_ent->port[port].bmdma_addr = bmdma_addr; ++ ++ scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port); ++ probe_ent->port[port].scr_addr = scr_addr; ++ ++ ata_std_ports(&probe_ent->port[port]); ++} ++ ++static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev) ++{ ++ struct ata_probe_ent *probe_ent; ++ struct ata_port_info *ppi = &svia_port_info; ++ ++ probe_ent = ata_pci_init_native_mode(pdev, &ppi); ++ if (!probe_ent) ++ return NULL; ++ ++ probe_ent->port[0].scr_addr = ++ svia_scr_addr(pci_resource_start(pdev, 5), 0); ++ probe_ent->port[1].scr_addr = ++ svia_scr_addr(pci_resource_start(pdev, 5), 1); ++ ++ return probe_ent; ++} ++ ++static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev) ++{ ++ struct ata_probe_ent *probe_ent; ++ unsigned int i; ++ ++ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); ++ if (!probe_ent) ++ return NULL; ++ ++ memset(probe_ent, 0, sizeof(*probe_ent)); ++ probe_ent->dev = pci_dev_to_dev(pdev); ++ INIT_LIST_HEAD(&probe_ent->node); ++ ++ probe_ent->sht = &svia_sht; ++ probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | ++ ATA_FLAG_NO_LEGACY; ++ probe_ent->port_ops = &svia_sata_ops; ++ probe_ent->n_ports = N_PORTS; ++ probe_ent->irq = pdev->irq; ++ probe_ent->irq_flags = SA_SHIRQ; ++ probe_ent->pio_mask = 0x1f; ++ probe_ent->mwdma_mask = 0x07; ++ probe_ent->udma_mask = 0x7f; ++ ++ for (i = 0; i < N_PORTS; i++) ++ vt6421_init_addrs(probe_ent, pdev, i); ++ ++ return probe_ent; ++} ++ ++static void svia_configure(struct pci_dev *pdev) ++{ ++ u8 tmp8; ++ ++ pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8); ++ printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n", ++ pci_name(pdev), ++ (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f); ++ ++ /* make sure SATA channels are enabled */ ++ pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8); ++ if ((tmp8 & ALL_PORTS) != ALL_PORTS) { ++ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n", ++ pci_name(pdev), (int) tmp8); ++ tmp8 |= ALL_PORTS; ++ pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8); ++ } ++ ++ /* make sure interrupts for each channel sent to us */ ++ pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8); ++ if ((tmp8 & ALL_PORTS) != ALL_PORTS) { ++ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n", ++ pci_name(pdev), (int) tmp8); ++ tmp8 |= ALL_PORTS; ++ pci_write_config_byte(pdev, SATA_INT_GATE, tmp8); ++ } ++ ++ /* make sure native mode is enabled */ ++ pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8); ++ if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { ++ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n", ++ pci_name(pdev), (int) tmp8); ++ tmp8 |= NATIVE_MODE_ALL; ++ pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); ++ } ++} ++ + static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) + { + static int printed_version; + unsigned int i; + int rc; +- struct ata_port_info *ppi; + struct ata_probe_ent *probe_ent; ++ int board_id = (int) ent->driver_data; ++ const int *bar_sizes; ++ int pci_dev_busy = 0; + u8 tmp8; + + if (!printed_version++) +@@ -181,20 +305,28 @@ + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + +- pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); +- if (tmp8 & SATA_2DEV) { +- printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n", +- pci_name(pdev), (int) tmp8); +- rc = -EIO; +- goto err_out_regions; ++ if (board_id == vt6420) { ++ pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); ++ if (tmp8 & SATA_2DEV) { ++ printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n", ++ pci_name(pdev), (int) tmp8); ++ rc = -EIO; ++ goto err_out_regions; ++ } ++ ++ bar_sizes = &svia_bar_sizes[0]; ++ } else { ++ bar_sizes = &vt6421_bar_sizes[0]; + } + + for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) + if ((pci_resource_start(pdev, i) == 0) || +- (pci_resource_len(pdev, i) < svia_bar_sizes[i])) { ++ (pci_resource_len(pdev, i) < bar_sizes[i])) { + printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n", + pci_name(pdev), i, + pci_resource_start(pdev, i), +@@ -207,8 +339,11 @@ + if (rc) + goto err_out_regions; + +- ppi = &svia_port_info; +- probe_ent = ata_pci_init_native_mode(pdev, &ppi); ++ if (board_id == vt6420) ++ probe_ent = vt6420_init_probe_ent(pdev); ++ else ++ probe_ent = vt6421_init_probe_ent(pdev); ++ + if (!probe_ent) { + printk(KERN_ERR DRV_NAME "(%s): out of memory\n", + pci_name(pdev)); +@@ -216,42 +351,7 @@ + goto err_out_regions; + } + +- probe_ent->port[0].scr_addr = +- svia_scr_addr(pci_resource_start(pdev, 5), 0); +- probe_ent->port[1].scr_addr = +- svia_scr_addr(pci_resource_start(pdev, 5), 1); +- +- pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8); +- printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n", +- pci_name(pdev), +- (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f); +- +- /* make sure SATA channels are enabled */ +- pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8); +- if ((tmp8 & ENAB_ALL) != ENAB_ALL) { +- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n", +- pci_name(pdev), (int) tmp8); +- tmp8 |= ENAB_ALL; +- pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8); +- } +- +- /* make sure interrupts for each channel sent to us */ +- pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8); +- if ((tmp8 & INT_GATE_ALL) != INT_GATE_ALL) { +- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n", +- pci_name(pdev), (int) tmp8); +- tmp8 |= INT_GATE_ALL; +- pci_write_config_byte(pdev, SATA_INT_GATE, tmp8); +- } +- +- /* make sure native mode is enabled */ +- pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8); +- if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { +- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n", +- pci_name(pdev), (int) tmp8); +- tmp8 |= NATIVE_MODE_ALL; +- pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); +- } ++ svia_configure(pdev); + + pci_set_master(pdev); + +@@ -262,7 +362,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + } + +diff -Nur linux-2.4.29/drivers/scsi/sata_vsc.c linux-mips/drivers/scsi/sata_vsc.c +--- linux-2.4.29/drivers/scsi/sata_vsc.c 2005-01-19 15:10:03.000000000 +0100 ++++ linux-mips/drivers/scsi/sata_vsc.c 2005-03-26 11:47:33.270191338 +0100 +@@ -155,7 +155,8 @@ + * + * Read the interrupt register and process for the devices that have them pending. + */ +-irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) ++static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, ++ struct pt_regs *regs) + { + struct ata_host_set *host_set = dev_instance; + unsigned int i; +@@ -218,6 +219,8 @@ + .phy_reset = sata_phy_reset, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, ++ .bmdma_stop = ata_bmdma_stop, ++ .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, +@@ -256,6 +259,7 @@ + static int printed_version; + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; ++ int pci_dev_busy = 0; + void *mmio_base; + int rc; + +@@ -275,13 +279,15 @@ + } + + rc = pci_request_regions(pdev, DRV_NAME); +- if (rc) ++ if (rc) { ++ pci_dev_busy = 1; + goto err_out; ++ } + + /* + * Use 32 bit DMA mask, because 64 bit address support is poor. + */ +- rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL); ++ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) + goto err_out_regions; + +@@ -348,7 +354,8 @@ + err_out_regions: + pci_release_regions(pdev); + err_out: +- pci_disable_device(pdev); ++ if (!pci_dev_busy) ++ pci_disable_device(pdev); + return rc; + } + +diff -Nur linux-2.4.29/drivers/scsi/sd.c linux-mips/drivers/scsi/sd.c +--- linux-2.4.29/drivers/scsi/sd.c 2003-08-25 13:44:42.000000000 +0200 ++++ linux-mips/drivers/scsi/sd.c 2005-03-26 11:47:33.274190681 +0100 +@@ -1220,7 +1220,7 @@ + goto cleanup_gendisks_part; + memset(sd_gendisks[i].part, 0, (SCSI_DISKS_PER_MAJOR << 4) * sizeof(struct hd_struct)); + sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4); +- sd_gendisks[i].nr_real = 0; ++ sd_gendisks[i].nr_real = SCSI_DISKS_PER_MAJOR; + sd_gendisks[i].real_devices = + (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR); + } +@@ -1333,7 +1333,6 @@ + rscsi_disks[i].device = SDp; + rscsi_disks[i].has_part_table = 0; + sd_template.nr_dev++; +- SD_GENDISK(i).nr_real++; + devnum = i % SCSI_DISKS_PER_MAJOR; + SD_GENDISK(i).de_arr[devnum] = SDp->de; + if (SDp->removable) +@@ -1447,7 +1446,6 @@ + SDp->attached--; + sd_template.dev_noticed--; + sd_template.nr_dev--; +- SD_GENDISK(i).nr_real--; + return; + } + return; +diff -Nur linux-2.4.29/drivers/scsi/st.c linux-mips/drivers/scsi/st.c +--- linux-2.4.29/drivers/scsi/st.c 2005-01-19 15:10:04.000000000 +0100 ++++ linux-mips/drivers/scsi/st.c 2005-03-26 11:47:33.279189861 +0100 +@@ -1641,7 +1641,7 @@ + if (STps->drv_block >= 0) + STps->drv_block += 1; + (STp->buffer)->buffer_bytes = 0; +- return (-EIO); ++ return (-ENOMEM); + } + (STp->buffer)->buffer_bytes = bytes - transfer; + } else { +@@ -3778,7 +3778,6 @@ + read: st_read, + write: st_write, + ioctl: st_ioctl, +- llseek: no_llseek, + open: st_open, + flush: st_flush, + release: st_release, +diff -Nur linux-2.4.29/drivers/scsi/sym53c8xx.c linux-mips/drivers/scsi/sym53c8xx.c +--- linux-2.4.29/drivers/scsi/sym53c8xx.c 2004-04-14 15:05:32.000000000 +0200 ++++ linux-mips/drivers/scsi/sym53c8xx.c 2005-03-26 11:47:34.823936333 +0100 +@@ -13182,7 +13182,7 @@ + ** descriptors. + */ + if (chip && (chip->features & FE_DAC)) { +- if (pci_set_dma_mask(pdev, (u64) 0xffffffffff)) ++ if (pci_set_dma_mask(pdev, (u64) 0xffffffffffULL)) + chip->features &= ~FE_DAC_IN_USE; + else + chip->features |= FE_DAC_IN_USE; diff -Nur linux-2.4.29/drivers/sound/au1550_i2s.c linux-mips/drivers/sound/au1550_i2s.c --- linux-2.4.29/drivers/sound/au1550_i2s.c 2005-01-19 15:10:04.000000000 +0100 -+++ linux-mips/drivers/sound/au1550_i2s.c 2005-02-12 04:07:11.000000000 +0100 ++++ linux-mips/drivers/sound/au1550_i2s.c 2005-03-26 11:47:35.065896621 +0100 @@ -41,6 +41,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * @@ -19103,63 +29598,744 @@ diff -Nur linux-2.4.29/drivers/tc/zs.h linux-mips/drivers/tc/zs.h unsigned char *xmit_buf; int xmit_head; int xmit_tail; -diff -Nur linux-2.4.29/drivers/video/Config.in linux-mips/drivers/video/Config.in ---- linux-2.4.29/drivers/video/Config.in 2004-02-18 14:36:31.000000000 +0100 -+++ linux-mips/drivers/video/Config.in 2005-02-12 04:07:18.000000000 +0100 -@@ -87,8 +87,8 @@ - if [ "$CONFIG_HP300" = "y" ]; then - define_bool CONFIG_FB_HP300 y - fi -- if [ "$ARCH" = "alpha" ]; then -- tristate ' TGA framebuffer support' CONFIG_FB_TGA -+ if [ "$ARCH" = "alpha" -o "$CONFIG_TC" = "y" ]; then -+ tristate ' TGA/SFB+ framebuffer support' CONFIG_FB_TGA - fi - if [ "$CONFIG_X86" = "y" ]; then - bool ' VESA VGA graphics console' CONFIG_FB_VESA -@@ -121,6 +121,17 @@ - hex ' Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000 - fi - fi -+ if [ "$CONFIG_SOC_AU1100" = "y" ]; then -+ bool ' Au1100 LCD Driver' CONFIG_FB_AU1100 -+ fi -+ -+ if [ "$CONFIG_SOC_AU1200" = "y" ]; then -+ bool ' Au1200 LCD Driver' CONFIG_FB_AU1200 -+ if [ "$CONFIG_FB_AU1200" = "y" ]; then -+ int ' Number of planes (1 to 4)' CONFIG_FB_AU1200_DEVS 1 -+ fi -+ fi -+ - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_PCI" != "n" ]; then - tristate ' Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX -@@ -178,9 +189,6 @@ - bool ' Use CRT on Pb1100 ' CONFIG_PB1500_CRT - bool ' Use TFT Panel on Pb1100 ' CONFIG_PB1500_TFT - fi -- if [ "$CONFIG_SOC_AU1100" = "y" ]; then -- bool ' Au1100 LCD Driver' CONFIG_FB_AU1100 -- fi - fi - fi - fi -diff -Nur linux-2.4.29/drivers/video/Makefile linux-mips/drivers/video/Makefile ---- linux-2.4.29/drivers/video/Makefile 2004-02-18 14:36:31.000000000 +0100 -+++ linux-mips/drivers/video/Makefile 2005-02-12 04:07:18.000000000 +0100 -@@ -87,6 +87,7 @@ - obj-$(CONFIG_FB_MAXINE) += maxinefb.o - obj-$(CONFIG_FB_TX3912) += tx3912fb.o - obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o -+obj-$(CONFIG_FB_AU1200) += au1200fb.o fbgen.o - obj-$(CONFIG_FB_IT8181) += it8181fb.o fbgen.o +diff -Nur linux-2.4.29/drivers/usb/devio.c linux-mips/drivers/usb/devio.c +--- linux-2.4.29/drivers/usb/devio.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/usb/devio.c 2005-03-26 11:47:35.208873156 +0100 +@@ -1132,6 +1132,8 @@ + /* ifno might usefully be passed ... */ + retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf); + /* size = min_t(int, size, retval)? */ ++ if (retval == -ENOIOCTLCMD) ++ retval = -ENOTTY; + } + } - subdir-$(CONFIG_STI_CONSOLE) += sti +@@ -1146,24 +1148,10 @@ + return retval; + } + +-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++static int usbdev_ioctl_exclusive(struct dev_state *ps, struct inode *inode, ++ unsigned int cmd, unsigned long arg) + { +- struct dev_state *ps = (struct dev_state *)file->private_data; +- int ret = -ENOIOCTLCMD; +- +- if (!(file->f_mode & FMODE_WRITE)) +- return -EPERM; +- down_read(&ps->devsem); +- if (!ps->dev) { +- up_read(&ps->devsem); +- return -ENODEV; +- } +- +- /* +- * grab device's exclusive_access mutex to prevent its driver from +- * using this device while it is being accessed by us. +- */ +- down(&ps->dev->exclusive_access); ++ int ret; + + switch (cmd) { + case USBDEVFS_CONTROL: +@@ -1194,14 +1182,6 @@ + inode->i_mtime = CURRENT_TIME; + break; + +- case USBDEVFS_GETDRIVER: +- ret = proc_getdriver(ps, (void *)arg); +- break; +- +- case USBDEVFS_CONNECTINFO: +- ret = proc_connectinfo(ps, (void *)arg); +- break; +- + case USBDEVFS_SETINTERFACE: + ret = proc_setintf(ps, (void *)arg); + break; +@@ -1220,6 +1200,53 @@ + ret = proc_unlinkurb(ps, (void *)arg); + break; + ++ case USBDEVFS_CLAIMINTERFACE: ++ ret = proc_claiminterface(ps, (void *)arg); ++ break; ++ ++ case USBDEVFS_RELEASEINTERFACE: ++ ret = proc_releaseinterface(ps, (void *)arg); ++ break; ++ ++ case USBDEVFS_IOCTL: ++ ret = proc_ioctl(ps, (void *) arg); ++ break; ++ ++ default: ++ ret = -ENOTTY; ++ } ++ return ret; ++} ++ ++static int usbdev_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dev_state *ps = file->private_data; ++ int ret; ++ ++ if (!(file->f_mode & FMODE_WRITE)) ++ return -EPERM; ++ down_read(&ps->devsem); ++ if (!ps->dev) { ++ up_read(&ps->devsem); ++ return -ENODEV; ++ } ++ ++ /* ++ * Some ioctls don't touch the device and can be called without ++ * grabbing its exclusive_access mutex; they are handled in this ++ * switch. Other ioctls which need exclusive_access are handled in ++ * usbdev_ioctl_exclusive(). ++ */ ++ switch (cmd) { ++ case USBDEVFS_GETDRIVER: ++ ret = proc_getdriver(ps, (void *)arg); ++ break; ++ ++ case USBDEVFS_CONNECTINFO: ++ ret = proc_connectinfo(ps, (void *)arg); ++ break; ++ + case USBDEVFS_REAPURB: + ret = proc_reapurb(ps, (void *)arg); + break; +@@ -1232,19 +1259,28 @@ + ret = proc_disconnectsignal(ps, (void *)arg); + break; + ++ case USBDEVFS_CONTROL: ++ case USBDEVFS_BULK: ++ case USBDEVFS_RESETEP: ++ case USBDEVFS_RESET: ++ case USBDEVFS_CLEAR_HALT: ++ case USBDEVFS_SETINTERFACE: ++ case USBDEVFS_SETCONFIGURATION: ++ case USBDEVFS_SUBMITURB: ++ case USBDEVFS_DISCARDURB: + case USBDEVFS_CLAIMINTERFACE: +- ret = proc_claiminterface(ps, (void *)arg); +- break; +- + case USBDEVFS_RELEASEINTERFACE: +- ret = proc_releaseinterface(ps, (void *)arg); +- break; +- + case USBDEVFS_IOCTL: +- ret = proc_ioctl(ps, (void *) arg); ++ ret = -ERESTARTSYS; ++ if (down_interruptible(&ps->dev->exclusive_access) == 0) { ++ ret = usbdev_ioctl_exclusive(ps, inode, cmd, arg); ++ up(&ps->dev->exclusive_access); ++ } + break; ++ ++ default: ++ ret = -ENOTTY; + } +- up(&ps->dev->exclusive_access); + up_read(&ps->devsem); + if (ret >= 0) + inode->i_atime = CURRENT_TIME; +diff -Nur linux-2.4.29/drivers/usb/hid-core.c linux-mips/drivers/usb/hid-core.c +--- linux-2.4.29/drivers/usb/hid-core.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/usb/hid-core.c 2005-03-26 11:47:35.374845916 +0100 +@@ -1064,18 +1064,31 @@ + static void hid_ctrl(struct urb *urb) + { + struct hid_device *hid = urb->context; ++ unsigned long flags; + + if (urb->status) + warn("ctrl urb status %d received", urb->status); + ++ spin_lock_irqsave(&hid->outlock, flags); ++ + hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1); + +- if (hid->outhead != hid->outtail) +- hid_submit_out(hid); ++ if (hid->outhead != hid->outtail) { ++ if (hid_submit_out(hid)) { ++ clear_bit(HID_OUT_RUNNING, &hid->iofl); ++ } ++ spin_unlock_irqrestore(&hid->outlock, flags); ++ return; ++ } ++ ++ clear_bit(HID_OUT_RUNNING, &hid->iofl); ++ spin_unlock_irqrestore(&hid->outlock, flags); + } + + void hid_write_report(struct hid_device *hid, struct hid_report *report) + { ++ unsigned long flags; ++ + if (hid->report_enum[report->type].numbered) { + hid->out[hid->outhead].buffer[0] = report->id; + hid_output_report(report, hid->out[hid->outhead].buffer + 1); +@@ -1087,13 +1100,18 @@ + + hid->out[hid->outhead].dr.wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); + ++ spin_lock_irqsave(&hid->outlock, flags); ++ + hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1); + + if (hid->outhead == hid->outtail) + hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1); + +- if (hid->urbout.status != -EINPROGRESS) +- hid_submit_out(hid); ++ if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl)) ++ if (hid_submit_out(hid)) ++ clear_bit(HID_OUT_RUNNING, &hid->iofl); ++ ++ spin_unlock_irqrestore(&hid->outlock, flags); + } + + int hid_open(struct hid_device *hid) +@@ -1333,6 +1351,8 @@ + return NULL; + } + ++ spin_lock_init(&hid->outlock); ++ + hid->version = hdesc->bcdHID; + hid->country = hdesc->bCountryCode; + hid->dev = dev; +diff -Nur linux-2.4.29/drivers/usb/hiddev.c linux-mips/drivers/usb/hiddev.c +--- linux-2.4.29/drivers/usb/hiddev.c 2004-08-08 01:26:05.000000000 +0200 ++++ linux-mips/drivers/usb/hiddev.c 2005-03-26 11:47:35.743785364 +0100 +@@ -328,6 +328,7 @@ + } + + schedule(); ++ set_current_state(TASK_INTERRUPTIBLE); + } + + set_current_state(TASK_RUNNING); +diff -Nur linux-2.4.29/drivers/usb/hid.h linux-mips/drivers/usb/hid.h +--- linux-2.4.29/drivers/usb/hid.h 2003-08-25 13:44:42.000000000 +0200 ++++ linux-mips/drivers/usb/hid.h 2005-03-26 11:47:35.742785528 +0100 +@@ -302,6 +302,8 @@ + #define HID_CLAIMED_INPUT 1 + #define HID_CLAIMED_HIDDEV 2 + ++#define HID_OUT_RUNNING 2 ++ + struct hid_input { + struct list_head list; + struct hid_report *report; +@@ -322,12 +324,15 @@ + struct usb_device *dev; /* USB device */ + int ifnum; /* USB interface number */ + ++ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ ++ + struct urb urb; /* USB URB structure */ + char buffer[HID_BUFFER_SIZE]; /* Rx buffer */ + + struct urb urbout; /* Output URB */ + struct hid_control_fifo out[HID_CONTROL_FIFO_SIZE]; /* Transmit buffer */ + unsigned char outhead, outtail; /* Tx buffer head & tail */ ++ spinlock_t outlock; /* Output fifo spinlock */ + + unsigned claimed; /* Claimed by hidinput, hiddev? */ + unsigned quirks; /* Various quirks the device can pull on us */ +diff -Nur linux-2.4.29/drivers/usb/serial/ftdi_sio.c linux-mips/drivers/usb/serial/ftdi_sio.c +--- linux-2.4.29/drivers/usb/serial/ftdi_sio.c 2005-01-19 15:10:07.000000000 +0100 ++++ linux-mips/drivers/usb/serial/ftdi_sio.c 2005-03-26 11:47:35.754783559 +0100 +@@ -737,8 +737,6 @@ + }; + + +- +- + static struct usb_serial_device_type ftdi_userdev_device = { + .owner = THIS_MODULE, + .name = "FTDI SIO compatible", +@@ -1240,15 +1238,6 @@ + } /* ftdi_HE_TIRA1_startup */ + + +-/* ftdi_shutdown is called from usbserial:usb_serial_disconnect +- * it is called when the usb device is disconnected +- * +- * usbserial:usb_serial_disconnect +- * calls __serial_close for each open of the port +- * shutdown is called then (ie ftdi_shutdown) +- */ +- +- + /* Startup for the 8U232AM chip */ + static int ftdi_userdev_startup (struct usb_serial *serial) + { +@@ -1273,6 +1262,14 @@ + } + + ++/* ftdi_shutdown is called from usbserial:usb_serial_disconnect ++ * it is called when the usb device is disconnected ++ * ++ * usbserial:usb_serial_disconnect ++ * calls __serial_close for each open of the port ++ * shutdown is called then (ie ftdi_shutdown) ++ */ ++ + static void ftdi_shutdown (struct usb_serial *serial) + { /* ftdi_shutdown */ + +@@ -1382,6 +1379,7 @@ + struct usb_serial *serial; + unsigned int c_cflag = port->tty->termios->c_cflag; + char buf[1]; ++ int err; + + dbg("%s", __FUNCTION__); + +@@ -1412,8 +1410,9 @@ + + /* shutdown our bulk read */ + if (port->read_urb) { +- if(usb_unlink_urb (port->read_urb)<0) +- err("Error unlinking urb"); ++ err = usb_unlink_urb (port->read_urb); ++ if (err < 0 && err != -ENODEV) ++ err("Error unlinking urb (%d)", err); + } + /* unlink the running write urbs */ + +diff -Nur linux-2.4.29/drivers/usb/serial/mct_u232.c linux-mips/drivers/usb/serial/mct_u232.c +--- linux-2.4.29/drivers/usb/serial/mct_u232.c 2005-01-19 15:10:08.000000000 +0100 ++++ linux-mips/drivers/usb/serial/mct_u232.c 2005-03-26 11:47:35.755783395 +0100 +@@ -86,26 +86,14 @@ + #include "usb-serial.h" + #include "mct_u232.h" + +- + /* + * Version Information + */ +-#define DRIVER_VERSION "v1.2" ++#define DRIVER_VERSION "z2.0" /* Linux in-kernel version */ + #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" + #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" + + /* +- * Some not properly written applications do not handle the return code of +- * write() correctly. This can result in character losses. A work-a-round +- * can be compiled in with the following definition. This work-a-round +- * should _NOT_ be part of an 'official' kernel release, of course! +- */ +-#undef FIX_WRITE_RETURN_CODE_PROBLEM +-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +-static int write_blocking; /* disabled by default */ +-#endif +- +-/* + * Function prototypes + */ + static int mct_u232_startup (struct usb_serial *serial); +@@ -114,13 +102,6 @@ + struct file *filp); + static void mct_u232_close (struct usb_serial_port *port, + struct file *filp); +-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +-static int mct_u232_write (struct usb_serial_port *port, +- int from_user, +- const unsigned char *buf, +- int count); +-static void mct_u232_write_bulk_callback (struct urb *urb); +-#endif + static void mct_u232_read_int_callback (struct urb *urb); + static void mct_u232_set_termios (struct usb_serial_port *port, + struct termios * old); +@@ -147,7 +128,7 @@ + + static struct usb_serial_device_type mct_u232_device = { + .owner = THIS_MODULE, +- .name = "Magic Control Technology USB-RS232", ++ .name = "MCT U232", + .id_table = id_table_combined, + .num_interrupt_in = 2, + .num_bulk_in = 0, +@@ -155,10 +136,6 @@ + .num_ports = 1, + .open = mct_u232_open, + .close = mct_u232_close, +-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +- .write = mct_u232_write, +- .write_bulk_callback = mct_u232_write_bulk_callback, +-#endif + .read_int_callback = mct_u232_read_int_callback, + .ioctl = mct_u232_ioctl, + .set_termios = mct_u232_set_termios, +@@ -167,9 +144,14 @@ + .shutdown = mct_u232_shutdown, + }; + ++struct mct_u232_interval_kludge { ++ int ecnt; /* Error counter */ ++ int ibase; /* Initial interval value */ ++}; + + struct mct_u232_private { + spinlock_t lock; ++ struct mct_u232_interval_kludge ik[2]; + unsigned int control_state; /* Modem Line Setting (TIOCM) */ + unsigned char last_lcr; /* Line Control Register */ + unsigned char last_lsr; /* Line Status Register */ +@@ -359,17 +341,13 @@ + struct mct_u232_private *priv; + struct usb_serial_port *port, *rport; + +- /* allocate the private data structure */ + priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +- /* set initial values for control structures */ ++ memset(priv, 0, sizeof(struct mct_u232_private)); + spin_lock_init(&priv->lock); +- priv->control_state = 0; +- priv->last_lsr = 0; +- priv->last_msr = 0; + serial->port->private = priv; +- ++ + init_waitqueue_head(&serial->port->write_wait); + + /* Puh, that's dirty */ +@@ -383,20 +361,27 @@ + rport->interrupt_in_urb = NULL; + port->read_urb->context = port; + ++ priv->ik[0].ibase = port->read_urb->interval; ++ priv->ik[1].ibase = port->interrupt_in_urb->interval; ++ + return (0); + } /* mct_u232_startup */ + + + static void mct_u232_shutdown (struct usb_serial *serial) + { ++ struct mct_u232_private *priv; + int i; + + dbg("%s", __FUNCTION__); + + for (i=0; i < serial->num_ports; ++i) { + /* My special items, the standard routines free my urbs */ +- if (serial->port[i].private) +- kfree(serial->port[i].private); ++ priv = serial->port[i].private; ++ if (priv) { ++ serial->port[i].private = NULL; ++ kfree(priv); ++ } + } + } /* mct_u232_shutdown */ + +@@ -448,16 +433,20 @@ + spin_unlock_irqrestore(&priv->lock, flags); + + port->read_urb->dev = port->serial->dev; ++ port->read_urb->interval = priv->ik[0].ibase; + retval = usb_submit_urb(port->read_urb); + if (retval) { +- err("usb_submit_urb(read bulk) failed"); ++ err("usb_submit_urb(read bulk) failed pipe 0x%x err %d", ++ port->read_urb->pipe, retval); + goto exit; + } + + port->interrupt_in_urb->dev = port->serial->dev; ++ port->interrupt_in_urb->interval = priv->ik[1].ibase; + retval = usb_submit_urb(port->interrupt_in_urb); + if (retval) +- err(" usb_submit_urb(read int) failed"); ++ err(" usb_submit_urb(read int) failed pipe 0x%x err %d", ++ port->interrupt_in_urb->pipe, retval); + + exit: + return 0; +@@ -476,109 +465,22 @@ + } + } /* mct_u232_close */ + +- +-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +-/* The generic routines work fine otherwise */ +- +-static int mct_u232_write (struct usb_serial_port *port, int from_user, +- const unsigned char *buf, int count) ++static void mct_u232_error_step (struct urb *urb, ++ struct mct_u232_private *priv, int n) + { +- struct usb_serial *serial = port->serial; +- int result, bytes_sent, size; +- +- dbg("%s - port %d", __FUNCTION__, port->number); +- +- if (count == 0) { +- dbg("%s - write request of 0 bytes", __FUNCTION__); +- return (0); +- } +- +- /* only do something if we have a bulk out endpoint */ +- if (!serial->num_bulk_out) +- return(0);; +- +- /* another write is still pending? */ +- if (port->write_urb->status == -EINPROGRESS) { +- dbg("%s - already writing", __FUNCTION__); +- return (0); +- } +- +- bytes_sent = 0; +- while (count > 0) { +- size = (count > port->bulk_out_size) ? port->bulk_out_size : count; +- +- usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf); +- +- if (from_user) { +- if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) { +- return -EFAULT; +- } +- } +- else { +- memcpy (port->write_urb->transfer_buffer, buf, size); +- } +- +- /* set up our urb */ +- FILL_BULK_URB(port->write_urb, serial->dev, +- usb_sndbulkpipe(serial->dev, +- port->bulk_out_endpointAddress), +- port->write_urb->transfer_buffer, size, +- ((serial->type->write_bulk_callback) ? +- serial->type->write_bulk_callback : +- mct_u232_write_bulk_callback), +- port); +- +- /* send the data out the bulk port */ +- result = usb_submit_urb(port->write_urb); +- if (result) { +- err("%s - failed submitting write urb, error %d", __FUNCTION__, result); +- return result; +- } +- +- bytes_sent += size; +- if (write_blocking) +- interruptible_sleep_on(&port->write_wait); +- else +- break; +- +- buf += size; +- count -= size; +- } +- +- return bytes_sent; +-} /* mct_u232_write */ +- +-static void mct_u232_write_bulk_callback (struct urb *urb) +-{ +- struct usb_serial_port *port = (struct usb_serial_port *)urb->context; +- struct usb_serial *serial = port->serial; +- struct tty_struct *tty = port->tty; +- +- dbg("%s - port %d", __FUNCTION__, port->number); +- +- if (!serial) { +- dbg("%s - bad serial pointer, exiting", __FUNCTION__); +- return; +- } ++ struct mct_u232_interval_kludge *ikp = &priv->ik[n]; + +- if (urb->status) { +- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, +- urb->status); +- return; +- } +- +- if (write_blocking) { +- wake_up_interruptible(&port->write_wait); +- tty_wakeup(tty); ++ if (ikp->ecnt >= 2) { ++ if (urb->interval) ++ err("%s - too many errors: " ++ "status %d pipe 0x%x interval %d", ++ __FUNCTION__, ++ urb->status, urb->pipe, urb->interval); ++ urb->interval = 0; + } else { +- /* from generic_write_bulk_callback */ +- queue_task(&port->tqueue, &tq_immediate); +- mark_bh(IMMEDIATE_BH); ++ ++ikp->ecnt; + } +- +- return; +-} /* mct_u232_write_bulk_callback */ +-#endif ++} + + static void mct_u232_read_int_callback (struct urb *urb) + { +@@ -589,21 +491,37 @@ + unsigned char *data = urb->transfer_buffer; + unsigned long flags; + +- dbg("%s - port %d", __FUNCTION__, port->number); +- + /* The urb might have been killed. */ + if (urb->status) { +- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, +- urb->status); ++ dbg("%s - nonzero status %d, pipe 0x%x flags 0x%x interval %d", ++ __FUNCTION__, ++ urb->status, urb->pipe, urb->transfer_flags, urb->interval); ++ /* ++ * The bad stuff happens when a device is disconnected. ++ * This can cause us to spin while trying to resubmit. ++ * Unfortunately, in kernel 2.4 error codes are wildly ++ * different between controllers, so the status is useless. ++ * Instead we just refuse to spin too much. ++ */ ++ if (urb == port->read_urb) ++ mct_u232_error_step(urb, priv, 0); ++ if (urb == port->interrupt_in_urb) ++ mct_u232_error_step(urb, priv, 1); + return; + } + if (!serial) { + dbg("%s - bad serial pointer, exiting", __FUNCTION__); + return; + } +- ++ ++ dbg("%s - port %d", __FUNCTION__, port->number); + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + ++ if (urb == port->read_urb) ++ priv->ik[0].ecnt = 0; ++ if (urb == port->interrupt_in_urb) ++ priv->ik[1].ecnt = 0; ++ + /* + * Work-a-round: handle the 'usual' bulk-in pipe here + */ +@@ -660,7 +578,6 @@ + /* INT urbs are automatically re-submitted */ + } /* mct_u232_read_int_callback */ + +- + static void mct_u232_set_termios (struct usb_serial_port *port, + struct termios *old_termios) + { +@@ -781,6 +698,21 @@ + } /* mct_u232_break_ctl */ + + ++static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file) ++{ ++ struct mct_u232_private *priv = (struct mct_u232_private *)port->private; ++ unsigned int control_state; ++ unsigned long flags; ++ ++ dbg("%s", __FUNCTION__); ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ control_state = priv->control_state; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return control_state; ++} ++ + static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, + unsigned int cmd, unsigned long arg) + { +@@ -794,8 +726,8 @@ + /* Based on code from acm.c and others */ + switch (cmd) { + case TIOCMGET: +- return put_user(priv->control_state, (unsigned long *) arg); +- break; ++ mask = mct_u232_tiocmget(port, file); ++ return put_user(mask, (unsigned long *) arg); + + case TIOCMSET: /* Turns on and off the lines as specified by the mask */ + case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ +@@ -865,12 +797,5 @@ + MODULE_DESCRIPTION( DRIVER_DESC ); + MODULE_LICENSE("GPL"); + +-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +-MODULE_PARM(write_blocking, "i"); +-MODULE_PARM_DESC(write_blocking, +- "The write function will block to write out all data"); +-#endif +- + MODULE_PARM(debug, "i"); + MODULE_PARM_DESC(debug, "Debug enabled or not"); +- +diff -Nur linux-2.4.29/drivers/usb/storage/transport.c linux-mips/drivers/usb/storage/transport.c +--- linux-2.4.29/drivers/usb/storage/transport.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/usb/storage/transport.c 2005-03-26 11:47:35.757783067 +0100 +@@ -1181,6 +1181,13 @@ + + /* if the command transfered well, then we go to the data stage */ + if (result == 0) { ++ ++ /* Genesys Logic interface chips need a 100us delay between ++ * the command phase and the data phase. Some systems need ++ * even more, probably because of clock rate inaccuracies. */ ++ if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS) ++ udelay(110); ++ + /* send/receive data payload, if there is any */ + if (bcb->DataTransferLength) { + usb_stor_transfer(srb, us); +diff -Nur linux-2.4.29/drivers/usb/storage/usb.c linux-mips/drivers/usb/storage/usb.c +--- linux-2.4.29/drivers/usb/storage/usb.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/drivers/usb/storage/usb.c 2005-03-26 11:47:35.758782903 +0100 +@@ -996,6 +996,15 @@ + */ + ss->htmplt.proc_dir = (void *)ss; + ++ /* According to the technical support people at Genesys Logic, ++ * devices using their chips have problems transferring more ++ * than 32 KB at a time. In practice people have found that ++ * 64 KB works okay and that's what Windows does. But we'll ++ * be conservative. ++ */ ++ if (ss->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS) ++ ss->htmplt.max_sectors = 64; ++ + /* Just before we start our control thread, initialize + * the device if it needs initialization */ + if (unusual_dev && unusual_dev->initFunction) +diff -Nur linux-2.4.29/drivers/usb/storage/usb.h linux-mips/drivers/usb/storage/usb.h +--- linux-2.4.29/drivers/usb/storage/usb.h 2004-08-08 01:26:05.000000000 +0200 ++++ linux-mips/drivers/usb/storage/usb.h 2005-03-26 11:47:35.759782739 +0100 +@@ -193,4 +193,7 @@ + /* Function to fill an inquiry response. See usb.c for details */ + extern void fill_inquiry_response(struct us_data *us, + unsigned char *data, unsigned int data_len); ++ ++/* Vendor ID list for devices that require special handling */ ++#define USB_VENDOR_ID_GENESYS 0x05e3 /* Genesys Logic */ + #endif diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200fb.c --- linux-2.4.29/drivers/video/au1200fb.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-mips/drivers/video/au1200fb.c 2005-02-11 22:16:44.000000000 +0100 -@@ -0,0 +1,1599 @@ ++++ linux-mips/drivers/video/au1200fb.c 2005-03-13 09:04:16.000000000 +0100 +@@ -0,0 +1,1564 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1200 LCD Driver. @@ -19213,18 +30389,6 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f +#include <video/fbcon-cfb32.h> +#define CMAPSIZE 16 + -+#ifdef CONFIG_MIPS_PB1200 -+#include <asm/pb1200.h> -+#endif -+ -+#ifdef CONFIG_MIPS_DB1200 -+#include <asm/db1200.h> -+#endif -+ -+#ifdef CONFIG_MIPS_FICMMP -+#include <asm/ficmmp.h> -+#endif -+ +#define AU1200_LCD_GET_WINENABLE 1 +#define AU1200_LCD_SET_WINENABLE 2 +#define AU1200_LCD_GET_WINLOCATION 3 @@ -19267,7 +30431,7 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + +AU1200_LCD *lcd = (AU1200_LCD *)AU1200_LCD_ADDR; +static int window_index = 0; /* default is zero */ -+static int panel_index = 0; /* default is zero */ ++static int panel_index = -1; /* default is call board_au1200fb_panel */ + +struct window_settings +{ @@ -19314,15 +30478,15 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f +#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 +#endif + -+static int panel_init (void); -+static int panel_shutdown (void); -+ ++extern int board_au1200fb_panel (void); ++extern int board_au1200fb_panel_init (void); ++extern int board_au1200fb_panel_shutdown (void); + +#if defined(CONFIG_FOCUS_ENHANCEMENTS) -+extern int focus_init_hdtv(void); -+extern int focus_init_component(void); -+extern int focus_init_cvsv(void); -+extern int focus_shutdown(void); ++extern int board_au1200fb_focus_init_hdtv(void); ++extern int board_au1200fb_focus_init_component(void); ++extern int board_au1200fb_focus_init_cvsv(void); ++extern int board_au1200fb_focus_shutdown(void); +#endif + +/* @@ -19502,8 +30666,8 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* mode_toyclksrc */ 0x00000004, /* 96MHz AUXPLL directly */ + /* mode_backlight */ 0x00000000, + /* mode_auxpll */ 8, /* 96MHz AUXPLL */ -+ /* device_init */ panel_init, -+ /* device_shutdown */ panel_shutdown, ++ /* device_init */ board_au1200fb_panel_init, ++ /* device_shutdown */ board_au1200fb_panel_shutdown, + }, + + { /* Index 6: Toshiba 640x480 TFT */ @@ -19520,8 +30684,8 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* mode_toyclksrc */ 0x00000004, /* 96MHz AUXPLL directly */ + /* mode_backlight */ 0x00000000, + /* mode_auxpll */ 8, /* 96MHz AUXPLL */ -+ /* device_init */ panel_init, -+ /* device_shutdown */ panel_shutdown, ++ /* device_init */ board_au1200fb_panel_init, ++ /* device_shutdown */ board_au1200fb_panel_shutdown, + }, + + { /* Index 7: Sharp 320x240 TFT */ @@ -19538,11 +30702,28 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* mode_toyclksrc */ 0x00000004, /* 96MHz AUXPLL directly */ + /* mode_backlight */ 0x00000000, + /* mode_auxpll */ 8, /* 96MHz AUXPLL */ -+ /* device_init */ panel_init, -+ /* device_shutdown */ panel_shutdown, ++ /* device_init */ board_au1200fb_panel_init, ++ /* device_shutdown */ board_au1200fb_panel_shutdown, ++ }, ++ { /* Index 8: Toppoly TD070WGCB2 7" 854x480 TFT */ ++ "Toppoly_TD070WGCB2", ++ 854, 480, ++ /* mode_screen */ LCD_SCREEN_SX_N(854) | LCD_SCREEN_SY_N(480), ++ /* mode_horztiming */ LCD_HORZTIMING_HND2_N(44) | LCD_HORZTIMING_HND1_N(44) | LCD_HORZTIMING_HPW_N(114), ++ /* mode_verttiming */ LCD_VERTTIMING_VND2_N(20) | LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), ++ /* mode_clkcontrol */ 0x00020001, /* /4=24Mhz */ ++ /* mode_pwmdiv */ 0x8000063f, ++ /* mode_pwmhi */ 0x03400000, ++ /* mode_outmask */ 0x00FCFCFC, ++ /* mode_fifoctrl */ 0x2f2f2f2f, ++ /* mode_toyclksrc */ 0x00000004, /* AUXPLL directly */ ++ /* mode_backlight */ 0x00000000, ++ /* mode_auxpll */ 8, /* 96MHz AUXPLL */ ++ /* device_init */ board_au1200fb_panel_init, ++ /* device_shutdown */ board_au1200fb_panel_shutdown, + }, +#if defined(CONFIG_FOCUS_ENHANCEMENTS) -+ { /* Index 8: Focus FS453 TV-Out 640x480 */ ++ { /* Index 9: Focus FS453 TV-Out 640x480 */ + "FS453_640x480 (Composite/S-Video)", + 640, 480, + /* mode_screen */ LCD_SCREEN_SX_N(640) | LCD_SCREEN_SY_N(480), @@ -19556,11 +30737,11 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* mode_toyclksrc */ 0x00000000, + /* mode_backlight */ 0x00000000, + /* mode_auxpll */ 8, /* 96MHz AUXPLL */ -+ /* device_init */ focus_init_cvsv, -+ /* device_shutdown */ focus_shutdown, ++ /* device_init */ board_au1200fb_focus_init_cvsv, ++ /* device_shutdown */ board_au1200fb_focus_shutdown, + }, + -+ { /* Index 9: Focus FS453 TV-Out 640x480 */ ++ { /* Index 10: Focus FS453 TV-Out 640x480 */ + "FS453_640x480 (Component Video)", + 640, 480, + /* mode_screen */ LCD_SCREEN_SX_N(640) | LCD_SCREEN_SY_N(480), @@ -19574,11 +30755,11 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* mode_toyclksrc */ 0x00000000, + /* mode_backlight */ 0x00000000, + /* mode_auxpll */ 8, /* 96MHz AUXPLL */ -+ /* device_init */ focus_init_component, -+ /* device_shutdown */ focus_shutdown, ++ /* device_init */ board_au1200fb_focus_init_component, ++ /* device_shutdown */ board_au1200fb_focus_shutdown, + }, + -+ { /* Index 10: Focus FS453 TV-Out 640x480 */ ++ { /* Index 11: Focus FS453 TV-Out 640x480 */ + "FS453_640x480 (HDTV)", + 720, 480, + /* mode_screen */ LCD_SCREEN_SX_N(720) | LCD_SCREEN_SY_N(480), @@ -19592,8 +30773,8 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* mode_toyclksrc */ 0x00000000, + /* mode_backlight */ 0x00000000, + /* mode_auxpll */ 8, /* 96MHz AUXPLL */ -+ /* device_init */ focus_init_hdtv, -+ /* device_shutdown */ focus_shutdown, ++ /* device_init */ board_au1200fb_focus_init_hdtv, ++ /* device_shutdown */ board_au1200fb_focus_shutdown, + }, +#endif +}; @@ -19666,36 +30847,6 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f +}; + + -+static int panel_init (void) -+{ -+#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200) -+ /* Apply power */ -+ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; -+ bcsr->board |= (BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL); -+ /*printk("panel_init(%s)\n", panel->name); */ -+#elif defined(CONFIG_MIPS_FICMMP) -+ /*Enable data buffers*/ -+ ficmmp_config_clear(FICMMP_CONFIG_LCMDATAOUT); -+ /*Take LCD out of reset*/ -+ ficmmp_config_set(FICMMP_CONFIG_LCMPWREN | FICMMP_CONFIG_LCMEN); -+#endif -+} -+ -+static int panel_shutdown (void) -+{ -+#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200) -+ /* Remove power */ -+ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; -+ bcsr->board &= ~(BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL); -+ /*printk("panel_shutdown(%s)\n", panel->name);*/ -+#elif defined(CONFIG_MIPS_FICMMP) -+ /*Disable data buffers*/ -+ ficmmp_config_set(FICMMP_CONFIG_LCMDATAOUT); -+ /*Put LCD in reset, remove power*/ -+ ficmmp_config_clear(FICMMP_CONFIG_LCMEN | FICMMP_CONFIG_LCMPWREN); -+#endif -+} -+ +static int +winbpp (unsigned int winctrl1) +{ @@ -20071,21 +31222,14 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + switch (blank_mode) { + case VESA_NO_BLANKING: + /* printk("turn on panel\n"); */ -+ if (panel->device_init) panel->device_init(); -+ lcd->screen |= LCD_SCREEN_SEN; -+ /* FIX!!! Need panel poweron callback */ ++ au1200_setpanel(panel); + break; + + case VESA_VSYNC_SUSPEND: + case VESA_HSYNC_SUSPEND: + case VESA_POWERDOWN: + /* printk("turn off panel\n"); */ -+ /* FIX!!! Need panel poweroff callback */ -+ if (panel->device_shutdown) panel->device_shutdown(); -+ lcd->screen &= ~LCD_SCREEN_SEN; -+ while ((lcd->intstatus & LCD_INT_SD) == 0) -+ ; -+ lcd->intstatus = LCD_INT_SD; ++ au1200_setpanel(NULL); + break; + default: + break; @@ -20318,6 +31462,9 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + if (panel->device_shutdown != NULL) panel->device_shutdown(); + } + ++ /* Check if only needing to turn off panel */ ++ if (panel == NULL) return; ++ + panel = newpanel; + + printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); @@ -20325,9 +31472,11 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* + * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) + */ -+ /* FIX!!! if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) */ ++ if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) + { + uint32 sys_clksrc; ++ /* WARNING! This should really be a check since other peripherals can ++ be affected by changins sys_auxpll */ + au_writel(panel->mode_auxpll, SYS_AUXPLL); + sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; + sys_clksrc |= panel->mode_toyclksrc; @@ -20571,6 +31720,7 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + +int __init au1200fb_init(void) +{ ++ int num_panels = sizeof(panels)/sizeof(struct panel_settings); + struct au1200fb_info *fb_info; + struct display *disp; + struct au1200fb_par *par; @@ -20580,6 +31730,12 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + /* + * Get the panel information/display mode + */ ++ if (panel_index < 0) ++ panel_index = board_au1200fb_panel(); ++ if ((panel_index < 0) || (panel_index >= num_panels)) { ++ printk("ERROR: INVALID PANEL %d\n", panel_index); ++ return -EINVAL; ++ } + panel = &panels[panel_index]; + win = &windows[window_index]; + @@ -20697,37 +31853,22 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.c linux-mips/drivers/video/au1200f + for(this_opt=strtok(options, ","); this_opt; + this_opt=strtok(NULL, ",")) { + if (!strncmp(this_opt, "panel:", 6)) { -+#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200) -+ /* Read Pb1200 Rotary Switch S11 to obtain default panel */ -+#ifdef CONFIG_MIPS_PB1200 -+ if (!strncmp(this_opt+6, "s11", 3)) -+#endif -+#ifdef CONFIG_MIPS_DB1200 -+ if (!strncmp(this_opt+6, "s7", 3)) -+#endif -+ { -+ BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR; -+ int p; -+ -+ p = bcsr->switches; -+ p >>= 8; -+ p &= 0x0F; -+ if (p >= num_panels) p = 0; -+ panel_index = p; ++ int i; ++ long int li; ++ char *endptr; ++ this_opt += 6; ++ ++ /* Panel name can be name, "bs" for board-switch, or number/index */ ++ li = simple_strtol(this_opt, &endptr, 0); ++ if (*endptr == '\0') { ++ panel_index = (int)li; ++ } ++ else if (strcmp(this_opt, "bs") == 0) { ++ panel_index = board_au1200fb_panel(); + } + else -+#elif defined(CONFIG_MIPS_FICMMP) -+ au1xxx_gpio_tristate(6); -+ -+ if(au1xxx_gpio_read(12) == 0) -+ panel_index = 8; -+ else -+ panel_index = 7; -+#endif -+ /* Get the panel name, everything else if fixed */ + for (i=0; i<num_panels; i++) { -+ if (!strncmp(this_opt+6, panels[i].name, -+ strlen(this_opt))) { ++ if (!strcmp(this_opt, panels[i].name)) { + panel_index = i; + break; + } @@ -21051,9 +32192,51 @@ diff -Nur linux-2.4.29/drivers/video/au1200fb.h linux-mips/drivers/video/au1200f + +/********************************************************************/ +#endif /* _AU1200LCD_H */ +diff -Nur linux-2.4.29/drivers/video/Config.in linux-mips/drivers/video/Config.in +--- linux-2.4.29/drivers/video/Config.in 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/video/Config.in 2005-03-26 11:47:35.761782411 +0100 +@@ -87,8 +87,8 @@ + if [ "$CONFIG_HP300" = "y" ]; then + define_bool CONFIG_FB_HP300 y + fi +- if [ "$ARCH" = "alpha" ]; then +- tristate ' TGA framebuffer support' CONFIG_FB_TGA ++ if [ "$ARCH" = "alpha" -o "$CONFIG_TC" = "y" ]; then ++ tristate ' TGA/SFB+ framebuffer support' CONFIG_FB_TGA + fi + if [ "$CONFIG_X86" = "y" ]; then + bool ' VESA VGA graphics console' CONFIG_FB_VESA +@@ -121,6 +121,17 @@ + hex ' Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000 + fi + fi ++ if [ "$CONFIG_SOC_AU1100" = "y" ]; then ++ bool ' Au1100 LCD Driver' CONFIG_FB_AU1100 ++ fi ++ ++ if [ "$CONFIG_SOC_AU1200" = "y" ]; then ++ bool ' Au1200 LCD Driver' CONFIG_FB_AU1200 ++ if [ "$CONFIG_FB_AU1200" = "y" ]; then ++ int ' Number of planes (1 to 4)' CONFIG_FB_AU1200_DEVS 1 ++ fi ++ fi ++ + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_PCI" != "n" ]; then + tristate ' Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX +@@ -178,9 +189,6 @@ + bool ' Use CRT on Pb1100 ' CONFIG_PB1500_CRT + bool ' Use TFT Panel on Pb1100 ' CONFIG_PB1500_TFT + fi +- if [ "$CONFIG_SOC_AU1100" = "y" ]; then +- bool ' Au1100 LCD Driver' CONFIG_FB_AU1100 +- fi + fi + fi + fi diff -Nur linux-2.4.29/drivers/video/fbmem.c linux-mips/drivers/video/fbmem.c --- linux-2.4.29/drivers/video/fbmem.c 2005-01-19 15:10:09.000000000 +0100 -+++ linux-mips/drivers/video/fbmem.c 2005-02-12 04:07:19.000000000 +0100 ++++ linux-mips/drivers/video/fbmem.c 2005-03-26 11:47:36.031738105 +0100 @@ -139,6 +139,8 @@ extern int e1356fb_setup(char*); extern int au1100fb_init(void); @@ -21352,6 +32535,17 @@ diff -Nur linux-2.4.29/drivers/video/ims332.h linux-mips/drivers/video/ims332.h + IMS332_CTRL_A_BOOT_ENABLE_VTG); + printk("\n"); +} +diff -Nur linux-2.4.29/drivers/video/Makefile linux-mips/drivers/video/Makefile +--- linux-2.4.29/drivers/video/Makefile 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/drivers/video/Makefile 2005-03-26 11:47:35.762782246 +0100 +@@ -87,6 +87,7 @@ + obj-$(CONFIG_FB_MAXINE) += maxinefb.o + obj-$(CONFIG_FB_TX3912) += tx3912fb.o + obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o ++obj-$(CONFIG_FB_AU1200) += au1200fb.o fbgen.o + obj-$(CONFIG_FB_IT8181) += it8181fb.o fbgen.o + + subdir-$(CONFIG_STI_CONSOLE) += sti diff -Nur linux-2.4.29/drivers/video/maxinefb.h linux-mips/drivers/video/maxinefb.h --- linux-2.4.29/drivers/video/maxinefb.h 2003-08-25 13:44:42.000000000 +0200 +++ linux-mips/drivers/video/maxinefb.h 1970-01-01 01:00:00.000000000 +0100 @@ -21845,6 +33039,658 @@ diff -Nur linux-2.4.29/fs/binfmt_elf.c linux-mips/fs/binfmt_elf.c elf.e_ehsize = sizeof(elf); elf.e_phentsize = sizeof(struct elf_phdr); elf.e_phnum = segs+1; /* Include notes */ +diff -Nur linux-2.4.29/fs/ext3/fsync.c linux-mips/fs/ext3/fsync.c +--- linux-2.4.29/fs/ext3/fsync.c 2002-11-29 00:53:15.000000000 +0100 ++++ linux-mips/fs/ext3/fsync.c 2005-03-26 11:47:36.070731705 +0100 +@@ -69,7 +69,7 @@ + if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) + ret |= fsync_inode_data_buffers(inode); + +- ext3_force_commit(inode->i_sb); ++ ret |= ext3_force_commit(inode->i_sb); + + return ret; + } +diff -Nur linux-2.4.29/fs/ext3/super.c linux-mips/fs/ext3/super.c +--- linux-2.4.29/fs/ext3/super.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/fs/ext3/super.c 2005-03-26 11:47:36.071731541 +0100 +@@ -1608,12 +1608,13 @@ + + static int ext3_sync_fs(struct super_block *sb) + { ++ int err; + tid_t target; + + sb->s_dirt = 0; + target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); +- log_wait_commit(EXT3_SB(sb)->s_journal, target); +- return 0; ++ err = log_wait_commit(EXT3_SB(sb)->s_journal, target); ++ return err; + } + + /* +diff -Nur linux-2.4.29/fs/file_table.c linux-mips/fs/file_table.c +--- linux-2.4.29/fs/file_table.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/fs/file_table.c 2005-03-26 11:47:36.063732854 +0100 +@@ -46,6 +46,7 @@ + f->f_version = ++event; + f->f_uid = current->fsuid; + f->f_gid = current->fsgid; ++ f->f_maxcount = INT_MAX; + list_add(&f->f_list, &anon_list); + file_list_unlock(); + return f; +@@ -91,6 +92,8 @@ + filp->f_uid = current->fsuid; + filp->f_gid = current->fsgid; + filp->f_op = dentry->d_inode->i_fop; ++ filp->f_maxcount = INT_MAX; ++ + if (filp->f_op->open) + return filp->f_op->open(dentry->d_inode, filp); + else +diff -Nur linux-2.4.29/fs/jbd/commit.c linux-mips/fs/jbd/commit.c +--- linux-2.4.29/fs/jbd/commit.c 2004-02-18 14:36:31.000000000 +0100 ++++ linux-mips/fs/jbd/commit.c 2005-03-26 11:47:36.078730392 +0100 +@@ -92,7 +92,7 @@ + struct buffer_head *wbuf[64]; + int bufs; + int flags; +- int err; ++ int err = 0; + unsigned long blocknr; + char *tagp = NULL; + journal_header_t *header; +@@ -299,6 +299,8 @@ + spin_unlock(&journal_datalist_lock); + unlock_journal(journal); + wait_on_buffer(bh); ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; + /* the journal_head may have been removed now */ + lock_journal(journal); + goto write_out_data; +@@ -326,6 +328,8 @@ + spin_unlock(&journal_datalist_lock); + unlock_journal(journal); + wait_on_buffer(bh); ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; + lock_journal(journal); + spin_lock(&journal_datalist_lock); + continue; /* List may have changed */ +@@ -351,6 +355,9 @@ + } + spin_unlock(&journal_datalist_lock); + ++ if (err) ++ __journal_abort_hard(journal); ++ + /* + * If we found any dirty or locked buffers, then we should have + * looped back up to the write_out_data label. If there weren't +@@ -541,6 +548,8 @@ + if (buffer_locked(bh)) { + unlock_journal(journal); + wait_on_buffer(bh); ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; + lock_journal(journal); + goto wait_for_iobuf; + } +@@ -602,6 +611,8 @@ + if (buffer_locked(bh)) { + unlock_journal(journal); + wait_on_buffer(bh); ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; + lock_journal(journal); + goto wait_for_ctlbuf; + } +@@ -650,6 +661,8 @@ + bh->b_end_io = journal_end_buffer_io_sync; + submit_bh(WRITE, bh); + wait_on_buffer(bh); ++ if (unlikely(!buffer_uptodate(bh))) ++ err = -EIO; + put_bh(bh); /* One for getblk() */ + journal_unlock_journal_head(descriptor); + } +@@ -661,6 +674,9 @@ + + skip_commit: /* The journal should be unlocked by now. */ + ++ if (err) ++ __journal_abort_hard(journal); ++ + /* Call any callbacks that had been registered for handles in this + * transaction. It is up to the callback to free any allocated + * memory. +diff -Nur linux-2.4.29/fs/jbd/journal.c linux-mips/fs/jbd/journal.c +--- linux-2.4.29/fs/jbd/journal.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/fs/jbd/journal.c 2005-03-26 11:47:36.079730228 +0100 +@@ -582,8 +582,10 @@ + * Wait for a specified commit to complete. + * The caller may not hold the journal lock. + */ +-void log_wait_commit (journal_t *journal, tid_t tid) ++int log_wait_commit (journal_t *journal, tid_t tid) + { ++ int err = 0; ++ + lock_kernel(); + #ifdef CONFIG_JBD_DEBUG + lock_journal(journal); +@@ -600,6 +602,12 @@ + sleep_on(&journal->j_wait_done_commit); + } + unlock_kernel(); ++ ++ if (unlikely(is_journal_aborted(journal))) { ++ printk(KERN_EMERG "journal commit I/O error\n"); ++ err = -EIO; ++ } ++ return err; + } + + /* +@@ -1326,7 +1334,7 @@ + + /* Wait for the log commit to complete... */ + if (transaction) +- log_wait_commit(journal, transaction->t_tid); ++ err = log_wait_commit(journal, transaction->t_tid); + + /* ...and flush everything in the log out to disk. */ + lock_journal(journal); +diff -Nur linux-2.4.29/fs/jbd/transaction.c linux-mips/fs/jbd/transaction.c +--- linux-2.4.29/fs/jbd/transaction.c 2004-08-08 01:26:05.000000000 +0200 ++++ linux-mips/fs/jbd/transaction.c 2005-03-26 11:47:36.081729900 +0100 +@@ -1484,7 +1484,7 @@ + * to wait for the commit to complete. + */ + if (handle->h_sync && !(current->flags & PF_MEMALLOC)) +- log_wait_commit(journal, tid); ++ err = log_wait_commit(journal, tid); + } + kfree(handle); + return err; +@@ -1509,7 +1509,7 @@ + goto out; + } + handle->h_sync = 1; +- journal_stop(handle); ++ ret = journal_stop(handle); + out: + unlock_kernel(); + return ret; +diff -Nur linux-2.4.29/fs/jfs/jfs_defragfs.h linux-mips/fs/jfs/jfs_defragfs.h +--- linux-2.4.29/fs/jfs/jfs_defragfs.h 2002-11-29 00:53:15.000000000 +0100 ++++ linux-mips/fs/jfs/jfs_defragfs.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,51 +0,0 @@ +-/* +- * Copyright (c) International Business Machines Corp., 2000-2001 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +- * the GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- */ +-#ifndef _H_JFS_DEFRAGFS +-#define _H_JFS_DEFRAGFS +- +-/* +- * defragfs parameter list +- */ +-struct defragfs { +- uint flag; /* 4: */ +- u8 dev; /* 1: */ +- u8 pad[3]; /* 3: */ +- s32 fileset; /* 4: */ +- u32 inostamp; /* 4: */ +- u32 ino; /* 4: */ +- u32 gen; /* 4: */ +- s64 xoff; /* 8: */ +- s64 old_xaddr; /* 8: */ +- s64 new_xaddr; /* 8: */ +- s32 xlen; /* 4: */ +-}; +- +-/* plist flag */ +-#define DEFRAGFS_SYNC 0x80000000 +-#define DEFRAGFS_COMMIT 0x40000000 +-#define DEFRAGFS_RELOCATE 0x10000000 +- +-#define INODE_TYPE 0x0000F000 /* IFREG or IFDIR */ +- +-#define EXTENT_TYPE 0x000000ff +-#define DTPAGE 0x00000001 +-#define XTPAGE 0x00000002 +-#define DATAEXT 0x00000004 +-#define EAEXT 0x00000008 +- +-#endif /* _H_JFS_DEFRAGFS */ +diff -Nur linux-2.4.29/fs/jfs/jfs_imap.c linux-mips/fs/jfs/jfs_imap.c +--- linux-2.4.29/fs/jfs/jfs_imap.c 2005-01-19 15:10:10.000000000 +0100 ++++ linux-mips/fs/jfs/jfs_imap.c 2005-03-26 11:47:36.085729244 +0100 +@@ -486,7 +486,6 @@ + /* read the page of fixed disk inode (AIT) in raw mode */ + mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1); + if (mp == NULL) { +- ip->i_sb = NULL; + ip->i_nlink = 1; /* Don't want iput() deleting it */ + iput(ip); + return (NULL); +@@ -499,7 +498,6 @@ + /* copy on-disk inode to in-memory inode */ + if ((copy_from_dinode(dp, ip)) != 0) { + /* handle bad return by returning NULL for ip */ +- ip->i_sb = NULL; + ip->i_nlink = 1; /* Don't want iput() deleting it */ + iput(ip); + /* release the page */ +diff -Nur linux-2.4.29/fs/jfs/jfs_metapage.c linux-mips/fs/jfs/jfs_metapage.c +--- linux-2.4.29/fs/jfs/jfs_metapage.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/fs/jfs/jfs_metapage.c 2005-03-26 11:47:36.086729079 +0100 +@@ -298,14 +298,14 @@ + mp = search_hash(hash_ptr, mapping, lblock); + if (mp) { + page_found: +- mp->count++; +- lock_metapage(mp); +- spin_unlock(&meta_lock); + if (test_bit(META_stale, &mp->flag)) { +- release_metapage(mp); +- yield(); /* Let other waiters release it, too */ ++ spin_unlock(&meta_lock); ++ yield(); + goto again; + } ++ mp->count++; ++ lock_metapage(mp); ++ spin_unlock(&meta_lock); + if (test_bit(META_discard, &mp->flag)) { + if (!new) { + jfs_error(inode->i_sb, +@@ -518,7 +518,6 @@ + } + + if (mp->page) { +- /* Releasing spinlock, we have to check mp->count later */ + set_bit(META_stale, &mp->flag); + spin_unlock(&meta_lock); + kunmap(mp->page); +@@ -555,12 +554,6 @@ + list_del(&mp->synclist); + LOGSYNC_UNLOCK(log); + } +- if (mp->count) { +- /* Someone else is trying to get this metpage */ +- unlock_metapage(mp); +- spin_unlock(&meta_lock); +- return; +- } + remove_from_hash(mp, meta_hash(mp->mapping, mp->index)); + spin_unlock(&meta_lock); + +@@ -589,12 +582,8 @@ + mp = search_hash(hash_ptr, mapping, lblock); + if (mp) { + if (test_bit(META_stale, &mp->flag)) { +- /* Racing with release_metapage */ +- mp->count++; +- lock_metapage(mp); + spin_unlock(&meta_lock); +- /* racing release_metapage should be done now */ +- release_metapage(mp); ++ yield(); + goto again; + } + +diff -Nur linux-2.4.29/fs/jfs/jfs_unicode.c linux-mips/fs/jfs/jfs_unicode.c +--- linux-2.4.29/fs/jfs/jfs_unicode.c 2004-04-14 15:05:40.000000000 +0200 ++++ linux-mips/fs/jfs/jfs_unicode.c 2005-03-26 11:47:36.089728587 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) International Business Machines Corp., 2000-2002 ++ * Copyright (C) International Business Machines Corp., 2000-2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -18,7 +18,7 @@ + + #include <linux/fs.h> + #include <linux/slab.h> +-#include "jfs_types.h" ++#include "jfs_incore.h" + #include "jfs_filsys.h" + #include "jfs_unicode.h" + #include "jfs_debug.h" +@@ -34,17 +34,40 @@ + { + int i; + int outlen = 0; ++ static int warn_again = 5; /* Only warn up to 5 times total */ ++ int warn = !!warn_again; /* once per string */ + +- for (i = 0; (i < len) && from[i]; i++) { +- int charlen; +- charlen = +- codepage->uni2char(le16_to_cpu(from[i]), &to[outlen], +- NLS_MAX_CHARSET_SIZE); +- if (charlen > 0) { +- outlen += charlen; +- } else { +- to[outlen++] = '?'; ++ if (codepage) { ++ for (i = 0; (i < len) && from[i]; i++) { ++ int charlen; ++ charlen = ++ codepage->uni2char(le16_to_cpu(from[i]), ++ &to[outlen], ++ NLS_MAX_CHARSET_SIZE); ++ if (charlen > 0) ++ outlen += charlen; ++ else ++ to[outlen++] = '?'; + } ++ } else { ++ for (i = 0; (i < len) && from[i]; i++) { ++ if (le16_to_cpu(from[i]) & 0xff00) { ++ if (warn) { ++ warn--; ++ warn_again--; ++ printk(KERN_ERR ++ "non-latin1 character 0x%x found in JFS file name\n", ++ le16_to_cpu(from[i])); ++ printk(KERN_ERR ++ "mount with iocharset=utf8 to access\n"); ++ } ++ to[i] = '?'; ++ } ++ else ++ to[i] = (char) (le16_to_cpu(from[i])); ++ } ++ outlen = i; ++ + } + to[outlen] = 0; + return outlen; +@@ -56,20 +79,27 @@ + * FUNCTION: Convert character string to unicode string + * + */ +-static int jfs_strtoUCS(wchar_t * to, const char *from, int len, ++static int jfs_strtoUCS(wchar_t * to, const unsigned char *from, int len, + struct nls_table *codepage) + { + int charlen; + int i; + +- for (i = 0; len && *from; i++, from += charlen, len -= charlen) { +- charlen = codepage->char2uni(from, len, &to[i]); +- if (charlen < 1) { +- jfs_err("jfs_strtoUCS: char2uni returned %d.", charlen); +- jfs_err("charset = %s, char = 0x%x", +- codepage->charset, (unsigned char) *from); +- return charlen; ++ if (codepage) { ++ for (i = 0; len && *from; i++, from += charlen, len -= charlen) ++ { ++ charlen = codepage->char2uni(from, len, &to[i]); ++ if (charlen < 1) { ++ jfs_err("jfs_strtoUCS: char2uni returned %d.", ++ charlen); ++ jfs_err("charset = %s, char = 0x%x", ++ codepage->charset, *from); ++ return charlen; ++ } + } ++ } else { ++ for (i = 0; (i < len) && from[i]; i++) ++ to[i] = (wchar_t) from[i]; + } + + to[i] = 0; +@@ -82,9 +112,9 @@ + * FUNCTION: Allocate and translate to unicode string + * + */ +-int get_UCSname(struct component_name * uniName, struct dentry *dentry, +- struct nls_table *nls_tab) ++int get_UCSname(struct component_name * uniName, struct dentry *dentry) + { ++ struct nls_table *nls_tab = JFS_SBI(dentry->d_sb)->nls_tab; + int length = dentry->d_name.len; + + if (length > JFS_NAME_MAX) +diff -Nur linux-2.4.29/fs/jfs/jfs_unicode.h linux-mips/fs/jfs/jfs_unicode.h +--- linux-2.4.29/fs/jfs/jfs_unicode.h 2002-11-29 00:53:15.000000000 +0100 ++++ linux-mips/fs/jfs/jfs_unicode.h 2005-03-26 11:47:36.095727603 +0100 +@@ -1,6 +1,6 @@ + /* +- * Copyright (c) International Business Machines Corp., 2000-2002 +- * Portions Copyright (c) Christoph Hellwig, 2001-2002 ++ * Copyright (C) International Business Machines Corp., 2000-2002 ++ * Portions Copyright (C) Christoph Hellwig, 2001-2002 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -30,8 +30,7 @@ + + extern signed char UniUpperTable[512]; + extern UNICASERANGE UniUpperRange[]; +-extern int get_UCSname(struct component_name *, struct dentry *, +- struct nls_table *); ++extern int get_UCSname(struct component_name *, struct dentry *); + extern int jfs_strfromUCS_le(char *, const wchar_t *, int, struct nls_table *); + + #define free_UCSname(COMP) kfree((COMP)->name) +diff -Nur linux-2.4.29/fs/jfs/namei.c linux-mips/fs/jfs/namei.c +--- linux-2.4.29/fs/jfs/namei.c 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/fs/jfs/namei.c 2005-03-26 11:47:36.096727438 +0100 +@@ -74,7 +74,7 @@ + * search parent directory for entry/freespace + * (dtSearch() returns parent directory page pinned) + */ +- if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&dname, dentry))) + goto out1; + + /* +@@ -195,7 +195,7 @@ + * search parent directory for entry/freespace + * (dtSearch() returns parent directory page pinned) + */ +- if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&dname, dentry))) + goto out1; + + /* +@@ -318,9 +318,8 @@ + goto out; + } + +- if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab))) { ++ if ((rc = get_UCSname(&dname, dentry))) + goto out; +- } + + tid = txBegin(dip->i_sb, 0); + +@@ -437,7 +436,7 @@ + + jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name); + +- if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&dname, dentry))) + goto out; + + IWRITE_LOCK(ip); +@@ -780,7 +779,7 @@ + /* + * scan parent directory for entry/freespace + */ +- if ((rc = get_UCSname(&dname, dentry, JFS_SBI(ip->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&dname, dentry))) + goto out; + + if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) +@@ -865,7 +864,7 @@ + * (dtSearch() returns parent directory page pinned) + */ + +- if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dip->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&dname, dentry))) + goto out1; + + /* +@@ -1044,12 +1043,10 @@ + old_ip = old_dentry->d_inode; + new_ip = new_dentry->d_inode; + +- if ((rc = get_UCSname(&old_dname, old_dentry, +- JFS_SBI(old_dir->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&old_dname, old_dentry))) + goto out1; + +- if ((rc = get_UCSname(&new_dname, new_dentry, +- JFS_SBI(old_dir->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&new_dname, new_dentry))) + goto out2; + + /* +@@ -1301,7 +1298,7 @@ + + jfs_info("jfs_mknod: %s", dentry->d_name.name); + +- if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dir->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&dname, dentry))) + goto out; + + ip = ialloc(dir, mode); +@@ -1376,8 +1373,7 @@ + else if (strcmp(name, "..") == 0) + inum = PARENT(dip); + else { +- if ((rc = +- get_UCSname(&key, dentry, JFS_SBI(dip->i_sb)->nls_tab))) ++ if ((rc = get_UCSname(&key, dentry))) + return ERR_PTR(rc); + rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP); + free_UCSname(&key); +diff -Nur linux-2.4.29/fs/jfs/super.c linux-mips/fs/jfs/super.c +--- linux-2.4.29/fs/jfs/super.c 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/fs/jfs/super.c 2005-03-26 11:47:36.101726618 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) International Business Machines Corp., 2000-2003 ++ * Copyright (C) International Business Machines Corp., 2000-2005 + * Portions Copyright (C) Christoph Hellwig, 2001-2002 + * + * This program is free software; you can redistribute it and/or modify +@@ -155,8 +155,10 @@ + rc = jfs_umount(sb); + if (rc) + jfs_err("jfs_umount failed with return code %d", rc); +- unload_nls(sbi->nls_tab); +- sbi->nls_tab = NULL; ++ if (sbi->nls_tab) { ++ unload_nls(sbi->nls_tab); ++ sbi->nls_tab = NULL; ++ } + + kfree(sbi); + } +@@ -182,7 +184,7 @@ + static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, + int *flag) + { +- void *nls_map = NULL; ++ void *nls_map = (void *)-1; /* -1: no change; NULL: none */ + char *this_char; + char *value; + struct jfs_sb_info *sbi = JFS_SBI(sb); +@@ -222,13 +224,12 @@ + } else if (!strcmp(this_char, "iocharset")) { + if (!value || !*value) + goto needs_arg; +- if (nls_map) /* specified iocharset twice! */ ++ if (nls_map && nls_map != (void *) -1) + unload_nls(nls_map); +- nls_map = load_nls(value); +- if (!nls_map) { +- printk(KERN_ERR "JFS: charset not found\n"); +- goto cleanup; +- } ++ if (!strcmp(value, "none")) ++ nls_map = NULL; ++ else ++ nls_map = load_nls(value); + } else if (!strcmp(this_char, "resize")) { + if (!value || !*value) { + *newLVSize = jfs_get_volume_size(sb); +@@ -250,9 +251,9 @@ + goto cleanup; + } + } +- if (nls_map) { ++ if (nls_map != (void *) -1) { + /* Discard old (if remount) */ +- if (sbi->nls_tab) ++ if (sbi->nls_tab && sbi->nls_tab != (void *) -1) + unload_nls(sbi->nls_tab); + sbi->nls_tab = nls_map; + } +@@ -260,7 +261,7 @@ + needs_arg: + printk(KERN_ERR "JFS: %s needs an argument\n", this_char); + cleanup: +- if (nls_map) ++ if (nls_map && nls_map != (void *) -1) + unload_nls(nls_map); + return 0; + } +@@ -328,6 +329,8 @@ + /* initialize the mount flag and determine the default error handler */ + flag = JFS_ERR_REMOUNT_RO; + ++ /* nls_tab will be set to NULL if no character mapping is requested */ ++ sbi->nls_tab = (void *) -1; + if (!parse_options((char *) data, sb, &newLVSize, &flag)) { + kfree(sbi); + return NULL; +@@ -378,7 +381,7 @@ + if (!sb->s_root) + goto out_no_root; + +- if (!sbi->nls_tab) ++ if (sbi->nls_tab == (void *) -1) + sbi->nls_tab = load_nls_default(); + + /* logical blocks are represented by 40 bits in pxd_t, etc. */ +diff -Nur linux-2.4.29/fs/nfsd/vfs.c linux-mips/fs/nfsd/vfs.c +--- linux-2.4.29/fs/nfsd/vfs.c 2004-11-17 12:54:21.000000000 +0100 ++++ linux-mips/fs/nfsd/vfs.c 2005-03-26 11:47:36.103726290 +0100 +@@ -466,6 +466,8 @@ + atomic_set(&filp->f_count, 1); + filp->f_dentry = dentry; + filp->f_vfsmnt = fhp->fh_export->ex_mnt; ++ filp->f_maxcount = INT_MAX; ++ + if (access & MAY_WRITE) { + filp->f_flags = O_WRONLY|O_LARGEFILE; + filp->f_mode = FMODE_WRITE; diff -Nur linux-2.4.29/fs/partitions/sgi.c linux-mips/fs/partitions/sgi.c --- linux-2.4.29/fs/partitions/sgi.c 2001-10-02 05:03:26.000000000 +0200 +++ linux-mips/fs/partitions/sgi.c 2004-08-11 22:30:07.000000000 +0200 @@ -21914,6 +33760,48 @@ diff -Nur linux-2.4.29/fs/proc/array.c linux-mips/fs/proc/array.c return len; } +diff -Nur linux-2.4.29/fs/proc/kcore.c linux-mips/fs/proc/kcore.c +--- linux-2.4.29/fs/proc/kcore.c 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/fs/proc/kcore.c 2005-03-26 11:47:36.107725633 +0100 +@@ -136,7 +136,10 @@ + } + *elf_buflen = sizeof(struct elfhdr) + + (*num_vma + 2)*sizeof(struct elf_phdr) + +- 3 * sizeof(struct memelfnote); ++ 3 * (sizeof(struct elf_note) + 4) + ++ sizeof(struct elf_prstatus) + ++ sizeof(struct elf_prpsinfo) + ++ sizeof(struct task_struct); + *elf_buflen = PAGE_ALIGN(*elf_buflen); + return (size - PAGE_OFFSET + *elf_buflen); + } +@@ -279,7 +282,7 @@ + + memset(&prstatus, 0, sizeof(struct elf_prstatus)); + +- nhdr->p_filesz = notesize(¬es[0]); ++ nhdr->p_filesz += notesize(¬es[0]); + bufp = storenote(¬es[0], bufp); + + /* set up the process info */ +@@ -296,7 +299,7 @@ + strcpy(prpsinfo.pr_fname, "vmlinux"); + strncpy(prpsinfo.pr_psargs, saved_command_line, ELF_PRARGSZ); + +- nhdr->p_filesz = notesize(¬es[1]); ++ nhdr->p_filesz += notesize(¬es[1]); + bufp = storenote(¬es[1], bufp); + + /* set up the task structure */ +@@ -305,7 +308,7 @@ + notes[2].datasz = sizeof(struct task_struct); + notes[2].data = current; + +- nhdr->p_filesz = notesize(¬es[2]); ++ nhdr->p_filesz += notesize(¬es[2]); + bufp = storenote(¬es[2], bufp); + + } /* end elf_kcore_store_hdr() */ diff -Nur linux-2.4.29/fs/proc/proc_misc.c linux-mips/fs/proc/proc_misc.c --- linux-2.4.29/fs/proc/proc_misc.c 2004-08-08 01:26:06.000000000 +0200 +++ linux-mips/fs/proc/proc_misc.c 2004-08-14 20:39:01.000000000 +0200 @@ -21953,6 +33841,128 @@ diff -Nur linux-2.4.29/fs/proc/proc_misc.c linux-mips/fs/proc/proc_misc.c + kstat.per_cpu_nice[cpu_logical_map(i)] \ + kstat.per_cpu_system[cpu_logical_map(i)])); proc_sprintf(page, &off, &len, +diff -Nur linux-2.4.29/fs/proc/proc_tty.c linux-mips/fs/proc/proc_tty.c +--- linux-2.4.29/fs/proc/proc_tty.c 2005-01-19 15:10:11.000000000 +0100 ++++ linux-mips/fs/proc/proc_tty.c 2005-03-26 11:47:36.107725633 +0100 +@@ -129,7 +129,7 @@ + } + + /* +- * Thsi function is called by register_tty_driver() to handle ++ * This function is called by tty_register_driver() to handle + * registering the driver's /proc handler into /proc/tty/driver/<foo> + */ + void proc_tty_register_driver(struct tty_driver *driver) +@@ -152,7 +152,7 @@ + } + + /* +- * This function is called by unregister_tty_driver() ++ * This function is called by tty_unregister_driver() + */ + void proc_tty_unregister_driver(struct tty_driver *driver) + { +diff -Nur linux-2.4.29/fs/read_write.c linux-mips/fs/read_write.c +--- linux-2.4.29/fs/read_write.c 2003-08-25 13:44:43.000000000 +0200 ++++ linux-mips/fs/read_write.c 2005-03-26 11:47:36.064732690 +0100 +@@ -40,6 +40,28 @@ + return -EISDIR; + } + ++int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count) ++{ ++ struct inode *inode; ++ loff_t pos; ++ ++ if (unlikely(count > file->f_maxcount)) ++ goto Einval; ++ ++ pos = *ppos; ++ ++ if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) ++ goto Einval; ++ ++ inode = file->f_dentry->d_inode; ++ if (inode->i_flock && MANDATORY_LOCK(inode)) ++ return locks_mandatory_area(read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, inode, file, *ppos, count); ++ return 0; ++ ++Einval: ++ return -EINVAL; ++} ++ + loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) + { + long long retval; +@@ -168,8 +190,8 @@ + file = fget(fd); + if (file) { + if (file->f_mode & FMODE_READ) { +- ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, +- file, file->f_pos, count); ++ ret = rw_verify_area(READ, file, &file->f_pos, count); ++ + if (!ret) { + ssize_t (*read)(struct file *, char *, size_t, loff_t *); + ret = -EINVAL; +@@ -193,9 +215,7 @@ + file = fget(fd); + if (file) { + if (file->f_mode & FMODE_WRITE) { +- struct inode *inode = file->f_dentry->d_inode; +- ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, +- file->f_pos, count); ++ ret = rw_verify_area(WRITE, file, &file->f_pos, count); + if (!ret) { + ssize_t (*write)(struct file *, const char *, size_t, loff_t *); + ret = -EINVAL; +@@ -224,7 +244,6 @@ + ssize_t ret, i; + io_fn_t fn; + iov_fn_t fnv; +- struct inode *inode; + + /* + * First get the "struct iovec" from user memory and +@@ -275,12 +294,11 @@ + goto out; + } + +- inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ +- ret = locks_verify_area((type == VERIFY_WRITE +- ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), +- inode, file, file->f_pos, tot_len); +- if (ret) goto out; ++ ret = rw_verify_area((type == VERIFY_WRITE ? READ : WRITE), ++ file, &file->f_pos, tot_len); ++ if (ret) ++ goto out; + + fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev); + if (fnv) { +@@ -383,8 +401,8 @@ + goto bad_file; + if (!(file->f_mode & FMODE_READ)) + goto out; +- ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, +- file, pos, count); ++ ret = rw_verify_area(READ, file, &pos, count); ++ + if (ret) + goto out; + ret = -EINVAL; +@@ -414,8 +432,8 @@ + goto bad_file; + if (!(file->f_mode & FMODE_WRITE)) + goto out; +- ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode, +- file, pos, count); ++ ret = rw_verify_area(WRITE, file, &pos, count); ++ + if (ret) + goto out; + ret = -EINVAL; diff -Nur linux-2.4.29/include/asm-alpha/param.h linux-mips/include/asm-alpha/param.h --- linux-2.4.29/include/asm-alpha/param.h 2000-11-08 08:37:31.000000000 +0100 +++ linux-mips/include/asm-alpha/param.h 2000-11-28 04:59:03.000000000 +0100 @@ -21966,6 +33976,18 @@ diff -Nur linux-2.4.29/include/asm-alpha/param.h linux-mips/include/asm-alpha/pa #endif #define EXEC_PAGESIZE 8192 +diff -Nur linux-2.4.29/include/asm-i386/acpi.h linux-mips/include/asm-i386/acpi.h +--- linux-2.4.29/include/asm-i386/acpi.h 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/include/asm-i386/acpi.h 2005-03-26 11:47:36.177714147 +0100 +@@ -121,6 +121,8 @@ + extern int acpi_strict; + extern int acpi_disabled; + extern int acpi_ht; ++extern int acpi_skip_timer_override; ++void __init check_acpi_pci(void); + static inline void disable_acpi(void) + { + acpi_disabled = 1; diff -Nur linux-2.4.29/include/asm-i386/param.h linux-mips/include/asm-i386/param.h --- linux-2.4.29/include/asm-i386/param.h 2000-10-27 20:04:43.000000000 +0200 +++ linux-mips/include/asm-i386/param.h 2000-11-23 03:00:55.000000000 +0100 @@ -21979,6 +34001,11 @@ diff -Nur linux-2.4.29/include/asm-i386/param.h linux-mips/include/asm-i386/para #endif #define EXEC_PAGESIZE 4096 +diff -Nur linux-2.4.29/include/asm-i386/pci-direct.h linux-mips/include/asm-i386/pci-direct.h +--- linux-2.4.29/include/asm-i386/pci-direct.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-mips/include/asm-i386/pci-direct.h 2005-03-18 13:13:30.000000000 +0100 +@@ -0,0 +1 @@ ++#include "asm-x86_64/pci-direct.h" diff -Nur linux-2.4.29/include/asm-ia64/param.h linux-mips/include/asm-ia64/param.h --- linux-2.4.29/include/asm-ia64/param.h 2004-04-14 15:05:40.000000000 +0200 +++ linux-mips/include/asm-ia64/param.h 2004-04-16 05:14:20.000000000 +0200 @@ -22012,6 +34039,124 @@ diff -Nur linux-2.4.29/include/asm-m68k/param.h linux-mips/include/asm-m68k/para #endif #define EXEC_PAGESIZE 8192 +diff -Nur linux-2.4.29/include/asm-mips/au1000_gpio.h linux-mips/include/asm-mips/au1000_gpio.h +--- linux-2.4.29/include/asm-mips/au1000_gpio.h 2002-11-29 00:53:15.000000000 +0100 ++++ linux-mips/include/asm-mips/au1000_gpio.h 2005-01-31 12:59:48.000000000 +0100 +@@ -30,6 +30,13 @@ + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + ++/* ++ * Revision history ++ * 01/31/02 0.01 Initial release. Steve Longerbeam, MontaVista ++ * 10/12/03 0.1 Added Au1100/Au1500, GPIO2, and bit operations. K.C. Nishio, AMD ++ * 08/05/04 0.11 Added Au1550 and Au1200. K.C. Nishio ++ */ ++ + #ifndef __AU1000_GPIO_H + #define __AU1000_GPIO_H + +@@ -44,13 +51,94 @@ + #define AU1000GPIO_TRISTATE _IOW (AU1000GPIO_IOC_MAGIC, 4, int) + #define AU1000GPIO_AVAIL_MASK _IOR (AU1000GPIO_IOC_MAGIC, 5, int) + ++// bit operations ++#define AU1000GPIO_BIT_READ _IOW (AU1000GPIO_IOC_MAGIC, 6, int) ++#define AU1000GPIO_BIT_SET _IOW (AU1000GPIO_IOC_MAGIC, 7, int) ++#define AU1000GPIO_BIT_CLEAR _IOW (AU1000GPIO_IOC_MAGIC, 8, int) ++#define AU1000GPIO_BIT_TRISTATE _IOW (AU1000GPIO_IOC_MAGIC, 9, int) ++#define AU1000GPIO_BIT_INIT _IOW (AU1000GPIO_IOC_MAGIC, 10, int) ++#define AU1000GPIO_BIT_TERM _IOW (AU1000GPIO_IOC_MAGIC, 11, int) ++ ++/* set this major numer same as the CRIS GPIO driver */ ++#define AU1X00_GPIO_MAJOR (120) ++ ++#define ENABLED_ZERO (0) ++#define ENABLED_ONE (1) ++#define ENABLED_10 (0x2) ++#define ENABLED_11 (0x3) ++#define ENABLED_111 (0x7) ++#define NOT_AVAIL (-1) ++#define AU1X00_MAX_PRIMARY_GPIO (32) ++ ++#define AU1000_GPIO_MINOR_MAX AU1X00_MAX_PRIMARY_GPIO ++/* Au1100, 1500, 1550 and 1200 have the secondary GPIO block */ ++#define AU1XX0_GPIO_MINOR_MAX (48) ++ ++#define AU1X00_GPIO_NAME "gpio" ++ ++/* GPIO pins which are not multiplexed */ ++#if defined(CONFIG_SOC_AU1000) ++ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 1) | (1 << 0)) ++ #define NATIVE_GPIO2PIN (0) ++#elif defined(CONFIG_SOC_AU1100) ++ #define NATIVE_GPIOPIN ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20) | (1 << 19) | (1 << 18) | \ ++ (1 << 17) | (1 << 16) | (1 << 7) | (1 << 1) | (1 << 0)) ++ #define NATIVE_GPIO2PIN (0) ++#elif defined(CONFIG_SOC_AU1500) ++ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 1) | (1 << 0)) ++ /* exclude the PCI reset output signal: GPIO[200], DMA_REQ2 and DMA_REQ3 */ ++ #define NATIVE_GPIO2PIN (0xfffe & ~((1 << 9) | (1 << 8))) ++#elif defined(CONFIG_SOC_AU1550) ++ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 6) | (1 << 1) | (1 << 0)) ++ /* please refere Au1550 Data Book, chapter 15 */ ++ #define NATIVE_GPIO2PIN (1 << 5) ++#elif defined(CONFIG_SOC_AU1200) ++ #define NATIVE_GPIOPIN ((1 << 7) | (1 << 5)) ++ #define NATIVE_GPIO2PIN (0) ++#endif ++ ++/* minor as u32 */ ++#define MINOR_TO_GPIOPIN(minor) ((minor < AU1X00_MAX_PRIMARY_GPIO) ? minor : (minor - AU1X00_MAX_PRIMARY_GPIO)) ++#define IS_PRIMARY_GPIOPIN(minor) ((minor < AU1X00_MAX_PRIMARY_GPIO) ? 1 : 0) ++ ++/* ++ * pin to minor mapping. ++ * GPIO0-GPIO31, minor=0-31. ++ * GPIO200-GPIO215, minor=32-47. ++ */ ++typedef struct _au1x00_gpio_bit_ctl { ++ int direction; // The direction of this GPIO pin. 0: IN, 1: OUT. ++ int data; // Pin output when itized (0/1), or at the term. 0/1/-1 (tristate). ++} au1x00_gpio_bit_ctl; ++ ++typedef struct _au1x00_gpio_driver { ++ const char *driver_name; ++ const char *name; ++ int name_base; /* offset of printed name */ ++ short major; /* major device number */ ++ short minor_start; /* start of minor device number*/ ++ short num; /* number of devices */ ++} au1x00_gpio_driver; ++ + #ifdef __KERNEL__ +-extern u32 get_au1000_avail_gpio_mask(void); +-extern int au1000gpio_tristate(u32 data); +-extern int au1000gpio_in(u32 *data); +-extern int au1000gpio_set(u32 data); +-extern int au1000gpio_clear(u32 data); +-extern int au1000gpio_out(u32 data); ++extern u32 get_au1000_avail_gpio_mask(u32 *avail_gpio2); ++extern int au1000gpio_tristate(u32 minor, u32 data); ++extern int au1000gpio_in(u32 minor, u32 *data); ++extern int au1000gpio_set(u32 minor, u32 data); ++extern int au1000gpio_clear(u32 minor, u32 data); ++extern int au1000gpio_out(u32 minor, u32 data); ++extern int au1000gpio_bit_read(u32 minor, u32 *read_data); ++extern int au1000gpio_bit_set(u32 minor); ++extern int au1000gpio_bit_clear(u32 minor); ++extern int au1000gpio_bit_tristate(u32 minor); ++extern int check_minor_to_gpio(u32 minor); ++extern int au1000gpio_bit_init(u32 minor, au1x00_gpio_bit_ctl *bit_opt); ++extern int au1000gpio_bit_term(u32 minor, au1x00_gpio_bit_ctl *bit_opt); ++ ++extern void gpio_register_devfs (au1x00_gpio_driver *driver, unsigned int flags, unsigned minor); ++extern void gpio_unregister_devfs (au1x00_gpio_driver *driver, unsigned minor); ++extern int gpio_register_driver(au1x00_gpio_driver *driver); ++extern int gpio_unregister_driver(au1x00_gpio_driver *driver); + #endif + + #endif diff -Nur linux-2.4.29/include/asm-mips/au1000.h linux-mips/include/asm-mips/au1000.h --- linux-2.4.29/include/asm-mips/au1000.h 2005-01-19 15:10:11.000000000 +0100 +++ linux-mips/include/asm-mips/au1000.h 2005-01-31 12:59:48.000000000 +0100 @@ -22682,124 +34827,6 @@ diff -Nur linux-2.4.29/include/asm-mips/au1000.h linux-mips/include/asm-mips/au1 + +#endif + -diff -Nur linux-2.4.29/include/asm-mips/au1000_gpio.h linux-mips/include/asm-mips/au1000_gpio.h ---- linux-2.4.29/include/asm-mips/au1000_gpio.h 2002-11-29 00:53:15.000000000 +0100 -+++ linux-mips/include/asm-mips/au1000_gpio.h 2005-01-31 12:59:48.000000000 +0100 -@@ -30,6 +30,13 @@ - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -+/* -+ * Revision history -+ * 01/31/02 0.01 Initial release. Steve Longerbeam, MontaVista -+ * 10/12/03 0.1 Added Au1100/Au1500, GPIO2, and bit operations. K.C. Nishio, AMD -+ * 08/05/04 0.11 Added Au1550 and Au1200. K.C. Nishio -+ */ -+ - #ifndef __AU1000_GPIO_H - #define __AU1000_GPIO_H - -@@ -44,13 +51,94 @@ - #define AU1000GPIO_TRISTATE _IOW (AU1000GPIO_IOC_MAGIC, 4, int) - #define AU1000GPIO_AVAIL_MASK _IOR (AU1000GPIO_IOC_MAGIC, 5, int) - -+// bit operations -+#define AU1000GPIO_BIT_READ _IOW (AU1000GPIO_IOC_MAGIC, 6, int) -+#define AU1000GPIO_BIT_SET _IOW (AU1000GPIO_IOC_MAGIC, 7, int) -+#define AU1000GPIO_BIT_CLEAR _IOW (AU1000GPIO_IOC_MAGIC, 8, int) -+#define AU1000GPIO_BIT_TRISTATE _IOW (AU1000GPIO_IOC_MAGIC, 9, int) -+#define AU1000GPIO_BIT_INIT _IOW (AU1000GPIO_IOC_MAGIC, 10, int) -+#define AU1000GPIO_BIT_TERM _IOW (AU1000GPIO_IOC_MAGIC, 11, int) -+ -+/* set this major numer same as the CRIS GPIO driver */ -+#define AU1X00_GPIO_MAJOR (120) -+ -+#define ENABLED_ZERO (0) -+#define ENABLED_ONE (1) -+#define ENABLED_10 (0x2) -+#define ENABLED_11 (0x3) -+#define ENABLED_111 (0x7) -+#define NOT_AVAIL (-1) -+#define AU1X00_MAX_PRIMARY_GPIO (32) -+ -+#define AU1000_GPIO_MINOR_MAX AU1X00_MAX_PRIMARY_GPIO -+/* Au1100, 1500, 1550 and 1200 have the secondary GPIO block */ -+#define AU1XX0_GPIO_MINOR_MAX (48) -+ -+#define AU1X00_GPIO_NAME "gpio" -+ -+/* GPIO pins which are not multiplexed */ -+#if defined(CONFIG_SOC_AU1000) -+ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 1) | (1 << 0)) -+ #define NATIVE_GPIO2PIN (0) -+#elif defined(CONFIG_SOC_AU1100) -+ #define NATIVE_GPIOPIN ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20) | (1 << 19) | (1 << 18) | \ -+ (1 << 17) | (1 << 16) | (1 << 7) | (1 << 1) | (1 << 0)) -+ #define NATIVE_GPIO2PIN (0) -+#elif defined(CONFIG_SOC_AU1500) -+ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 1) | (1 << 0)) -+ /* exclude the PCI reset output signal: GPIO[200], DMA_REQ2 and DMA_REQ3 */ -+ #define NATIVE_GPIO2PIN (0xfffe & ~((1 << 9) | (1 << 8))) -+#elif defined(CONFIG_SOC_AU1550) -+ #define NATIVE_GPIOPIN ((1 << 15) | (1 << 8) | (1 << 7) | (1 << 6) | (1 << 1) | (1 << 0)) -+ /* please refere Au1550 Data Book, chapter 15 */ -+ #define NATIVE_GPIO2PIN (1 << 5) -+#elif defined(CONFIG_SOC_AU1200) -+ #define NATIVE_GPIOPIN ((1 << 7) | (1 << 5)) -+ #define NATIVE_GPIO2PIN (0) -+#endif -+ -+/* minor as u32 */ -+#define MINOR_TO_GPIOPIN(minor) ((minor < AU1X00_MAX_PRIMARY_GPIO) ? minor : (minor - AU1X00_MAX_PRIMARY_GPIO)) -+#define IS_PRIMARY_GPIOPIN(minor) ((minor < AU1X00_MAX_PRIMARY_GPIO) ? 1 : 0) -+ -+/* -+ * pin to minor mapping. -+ * GPIO0-GPIO31, minor=0-31. -+ * GPIO200-GPIO215, minor=32-47. -+ */ -+typedef struct _au1x00_gpio_bit_ctl { -+ int direction; // The direction of this GPIO pin. 0: IN, 1: OUT. -+ int data; // Pin output when itized (0/1), or at the term. 0/1/-1 (tristate). -+} au1x00_gpio_bit_ctl; -+ -+typedef struct _au1x00_gpio_driver { -+ const char *driver_name; -+ const char *name; -+ int name_base; /* offset of printed name */ -+ short major; /* major device number */ -+ short minor_start; /* start of minor device number*/ -+ short num; /* number of devices */ -+} au1x00_gpio_driver; -+ - #ifdef __KERNEL__ --extern u32 get_au1000_avail_gpio_mask(void); --extern int au1000gpio_tristate(u32 data); --extern int au1000gpio_in(u32 *data); --extern int au1000gpio_set(u32 data); --extern int au1000gpio_clear(u32 data); --extern int au1000gpio_out(u32 data); -+extern u32 get_au1000_avail_gpio_mask(u32 *avail_gpio2); -+extern int au1000gpio_tristate(u32 minor, u32 data); -+extern int au1000gpio_in(u32 minor, u32 *data); -+extern int au1000gpio_set(u32 minor, u32 data); -+extern int au1000gpio_clear(u32 minor, u32 data); -+extern int au1000gpio_out(u32 minor, u32 data); -+extern int au1000gpio_bit_read(u32 minor, u32 *read_data); -+extern int au1000gpio_bit_set(u32 minor); -+extern int au1000gpio_bit_clear(u32 minor); -+extern int au1000gpio_bit_tristate(u32 minor); -+extern int check_minor_to_gpio(u32 minor); -+extern int au1000gpio_bit_init(u32 minor, au1x00_gpio_bit_ctl *bit_opt); -+extern int au1000gpio_bit_term(u32 minor, au1x00_gpio_bit_ctl *bit_opt); -+ -+extern void gpio_register_devfs (au1x00_gpio_driver *driver, unsigned int flags, unsigned minor); -+extern void gpio_unregister_devfs (au1x00_gpio_driver *driver, unsigned minor); -+extern int gpio_register_driver(au1x00_gpio_driver *driver); -+extern int gpio_unregister_driver(au1x00_gpio_driver *driver); - #endif - - #endif diff -Nur linux-2.4.29/include/asm-mips/au1000_pcmcia.h linux-mips/include/asm-mips/au1000_pcmcia.h --- linux-2.4.29/include/asm-mips/au1000_pcmcia.h 2005-01-19 15:10:11.000000000 +0100 +++ linux-mips/include/asm-mips/au1000_pcmcia.h 2005-01-31 12:59:48.000000000 +0100 @@ -23808,7 +35835,7 @@ diff -Nur linux-2.4.29/include/asm-mips/hazards.h linux-mips/include/asm-mips/ha #endif /* _ASM_HAZARDS_H */ diff -Nur linux-2.4.29/include/asm-mips/mipsregs.h linux-mips/include/asm-mips/mipsregs.h --- linux-2.4.29/include/asm-mips/mipsregs.h 2005-01-19 15:10:12.000000000 +0100 -+++ linux-mips/include/asm-mips/mipsregs.h 2005-02-12 04:07:58.000000000 +0100 ++++ linux-mips/include/asm-mips/mipsregs.h 2005-03-26 11:47:36.210708732 +0100 @@ -757,10 +757,18 @@ #define read_c0_config1() __read_32bit_c0_register($16, 1) #define read_c0_config2() __read_32bit_c0_register($16, 2) @@ -24708,7 +36735,7 @@ diff -Nur linux-2.4.29/include/asm-mips64/hazards.h linux-mips/include/asm-mips6 #endif /* _ASM_HAZARDS_H */ diff -Nur linux-2.4.29/include/asm-mips64/mipsregs.h linux-mips/include/asm-mips64/mipsregs.h --- linux-2.4.29/include/asm-mips64/mipsregs.h 2005-01-19 15:10:12.000000000 +0100 -+++ linux-mips/include/asm-mips64/mipsregs.h 2005-02-12 04:08:02.000000000 +0100 ++++ linux-mips/include/asm-mips64/mipsregs.h 2005-03-26 11:47:36.406676569 +0100 @@ -757,10 +757,18 @@ #define read_c0_config1() __read_32bit_c0_register($16, 1) #define read_c0_config2() __read_32bit_c0_register($16, 2) @@ -24868,6 +36895,18 @@ diff -Nur linux-2.4.29/include/asm-ppc/param.h linux-mips/include/asm-ppc/param. #endif #define EXEC_PAGESIZE 4096 +diff -Nur linux-2.4.29/include/asm-ppc/processor.h linux-mips/include/asm-ppc/processor.h +--- linux-2.4.29/include/asm-ppc/processor.h 2004-04-14 15:05:40.000000000 +0200 ++++ linux-mips/include/asm-ppc/processor.h 2005-03-26 11:47:36.510659503 +0100 +@@ -678,7 +678,7 @@ + #define PVR_440GP_RC2 0x40200481 + #define PVR_440GX_RA 0x51b21850 + #define PVR_440GX_RB 0x51b21851 +-#define PVR_440GX_RB1 0x51b21852 ++#define PVR_440GX_RC 0x51b21892 + #define PVR_601 0x00010000 + #define PVR_602 0x00050000 + #define PVR_603 0x00030000 diff -Nur linux-2.4.29/include/asm-s390/param.h linux-mips/include/asm-s390/param.h --- linux-2.4.29/include/asm-s390/param.h 2001-02-13 23:13:44.000000000 +0100 +++ linux-mips/include/asm-s390/param.h 2001-03-09 21:34:48.000000000 +0100 @@ -24907,6 +36946,468 @@ diff -Nur linux-2.4.29/include/asm-sparc/param.h linux-mips/include/asm-sparc/pa #endif #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */ +diff -Nur linux-2.4.29/include/asm-sparc/system.h linux-mips/include/asm-sparc/system.h +--- linux-2.4.29/include/asm-sparc/system.h 2004-02-18 14:36:32.000000000 +0100 ++++ linux-mips/include/asm-sparc/system.h 2005-03-26 11:47:36.945588121 +0100 +@@ -295,11 +295,11 @@ + #define wmb() mb() + #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) + #define set_wmb(__var, __value) set_mb(__var, __value) +-#define smp_mb() __asm__ __volatile__("":::"memory"); +-#define smp_rmb() __asm__ __volatile__("":::"memory"); +-#define smp_wmb() __asm__ __volatile__("":::"memory"); ++#define smp_mb() __asm__ __volatile__("":::"memory") ++#define smp_rmb() __asm__ __volatile__("":::"memory") ++#define smp_wmb() __asm__ __volatile__("":::"memory") + +-#define nop() __asm__ __volatile__ ("nop"); ++#define nop() __asm__ __volatile__ ("nop") + + /* This has special calling conventions */ + #ifndef CONFIG_SMP +diff -Nur linux-2.4.29/include/asm-sparc64/atomic.h linux-mips/include/asm-sparc64/atomic.h +--- linux-2.4.29/include/asm-sparc64/atomic.h 2001-07-20 03:11:13.000000000 +0200 ++++ linux-mips/include/asm-sparc64/atomic.h 2005-03-26 11:47:36.964585003 +0100 +@@ -8,31 +8,59 @@ + #ifndef __ARCH_SPARC64_ATOMIC__ + #define __ARCH_SPARC64_ATOMIC__ + ++#include <linux/config.h> ++ + typedef struct { volatile int counter; } atomic_t; + #define ATOMIC_INIT(i) { (i) } + + #define atomic_read(v) ((v)->counter) + #define atomic_set(v, i) (((v)->counter) = i) + +-extern int __atomic_add(int, atomic_t *); +-extern int __atomic_sub(int, atomic_t *); ++extern void atomic_add(int, atomic_t *); ++extern void atomic_sub(int, atomic_t *); ++ ++extern int atomic_add_ret(int, atomic_t *); ++extern int atomic_sub_ret(int, atomic_t *); ++ ++#define atomic_dec_return(v) atomic_sub_ret(1, v) ++ ++#define atomic_inc_return(v) atomic_add_ret(1, v) ++ ++#define atomic_sub_return(i, v) atomic_sub_ret(i, v) ++ ++#define atomic_add_return(i, v) atomic_add_ret(i, v) ++ ++/* ++ * atomic_inc_and_test - increment and test ++ * @v: pointer of type atomic_t ++ * ++ * Atomically increments @v by 1 ++ * and returns true if the result is zero, or false for all ++ * other cases. ++ */ ++#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) ++ ++#define atomic_sub_and_test(i, v) (atomic_sub_ret(i, v) == 0) + +-#define atomic_add(i, v) ((void)__atomic_add(i, v)) +-#define atomic_sub(i, v) ((void)__atomic_sub(i, v)) ++#define atomic_dec_and_test(v) (atomic_sub_ret(1, v) == 0) + +-#define atomic_dec_return(v) __atomic_sub(1, v) +-#define atomic_inc_return(v) __atomic_add(1, v) ++#define atomic_inc(v) atomic_add(1, v) + +-#define atomic_sub_and_test(i, v) (__atomic_sub(i, v) == 0) +-#define atomic_dec_and_test(v) (__atomic_sub(1, v) == 0) ++#define atomic_dec(v) atomic_sub(1, v) + +-#define atomic_inc(v) ((void)__atomic_add(1, v)) +-#define atomic_dec(v) ((void)__atomic_sub(1, v)) ++#define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0) + + /* Atomic operations are already serializing */ ++#ifdef CONFIG_SMP ++#define smp_mb__before_atomic_dec() membar("#StoreLoad | #LoadLoad") ++#define smp_mb__after_atomic_dec() membar("#StoreLoad | #StoreStore") ++#define smp_mb__before_atomic_inc() membar("#StoreLoad | #LoadLoad") ++#define smp_mb__after_atomic_inc() membar("#StoreLoad | #StoreStore") ++#else + #define smp_mb__before_atomic_dec() barrier() + #define smp_mb__after_atomic_dec() barrier() + #define smp_mb__before_atomic_inc() barrier() + #define smp_mb__after_atomic_inc() barrier() ++#endif + + #endif /* !(__ARCH_SPARC64_ATOMIC__) */ +diff -Nur linux-2.4.29/include/asm-sparc64/bitops.h linux-mips/include/asm-sparc64/bitops.h +--- linux-2.4.29/include/asm-sparc64/bitops.h 2001-12-21 18:42:03.000000000 +0100 ++++ linux-mips/include/asm-sparc64/bitops.h 2005-03-26 11:47:37.017576306 +0100 +@@ -1,4 +1,4 @@ +-/* $Id$ ++/* $Id$ + * bitops.h: Bit string operations on the V9. + * + * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) +@@ -7,114 +7,126 @@ + #ifndef _SPARC64_BITOPS_H + #define _SPARC64_BITOPS_H + ++#include <linux/config.h> ++#include <linux/compiler.h> + #include <asm/byteorder.h> + +-extern long ___test_and_set_bit(unsigned long nr, volatile void *addr); +-extern long ___test_and_clear_bit(unsigned long nr, volatile void *addr); +-extern long ___test_and_change_bit(unsigned long nr, volatile void *addr); +- +-#define test_and_set_bit(nr,addr) ({___test_and_set_bit(nr,addr)!=0;}) +-#define test_and_clear_bit(nr,addr) ({___test_and_clear_bit(nr,addr)!=0;}) +-#define test_and_change_bit(nr,addr) ({___test_and_change_bit(nr,addr)!=0;}) +-#define set_bit(nr,addr) ((void)___test_and_set_bit(nr,addr)) +-#define clear_bit(nr,addr) ((void)___test_and_clear_bit(nr,addr)) +-#define change_bit(nr,addr) ((void)___test_and_change_bit(nr,addr)) ++extern int test_and_set_bit(unsigned long nr, volatile void *addr); ++extern int test_and_clear_bit(unsigned long nr, volatile void *addr); ++extern int test_and_change_bit(unsigned long nr, volatile void *addr); ++extern void set_bit(unsigned long nr, volatile void *addr); ++extern void clear_bit(unsigned long nr, volatile void *addr); ++extern void change_bit(unsigned long nr, volatile void *addr); + + /* "non-atomic" versions... */ +-#define __set_bit(X,Y) \ +-do { unsigned long __nr = (X); \ +- long *__m = ((long *) (Y)) + (__nr >> 6); \ +- *__m |= (1UL << (__nr & 63)); \ +-} while (0) +-#define __clear_bit(X,Y) \ +-do { unsigned long __nr = (X); \ +- long *__m = ((long *) (Y)) + (__nr >> 6); \ +- *__m &= ~(1UL << (__nr & 63)); \ +-} while (0) +-#define __change_bit(X,Y) \ +-do { unsigned long __nr = (X); \ +- long *__m = ((long *) (Y)) + (__nr >> 6); \ +- *__m ^= (1UL << (__nr & 63)); \ +-} while (0) +-#define __test_and_set_bit(X,Y) \ +-({ unsigned long __nr = (X); \ +- long *__m = ((long *) (Y)) + (__nr >> 6); \ +- long __old = *__m; \ +- long __mask = (1UL << (__nr & 63)); \ +- *__m = (__old | __mask); \ +- ((__old & __mask) != 0); \ +-}) +-#define __test_and_clear_bit(X,Y) \ +-({ unsigned long __nr = (X); \ +- long *__m = ((long *) (Y)) + (__nr >> 6); \ +- long __old = *__m; \ +- long __mask = (1UL << (__nr & 63)); \ +- *__m = (__old & ~__mask); \ +- ((__old & __mask) != 0); \ +-}) +-#define __test_and_change_bit(X,Y) \ +-({ unsigned long __nr = (X); \ +- long *__m = ((long *) (Y)) + (__nr >> 6); \ +- long __old = *__m; \ +- long __mask = (1UL << (__nr & 63)); \ +- *__m = (__old ^ __mask); \ +- ((__old & __mask) != 0); \ +-}) + +-#define smp_mb__before_clear_bit() do { } while(0) +-#define smp_mb__after_clear_bit() do { } while(0) ++static __inline__ void __set_bit(int nr, volatile void *addr) ++{ ++ unsigned long *m; ++ ++ m = ((unsigned long *)addr) + (nr >> 6); ++ *m |= (1UL << (nr & 63)); ++} ++ ++static __inline__ void __clear_bit(int nr, volatile void *addr) ++{ ++ unsigned long *m; ++ ++ m = ((unsigned long *)addr) + (nr >> 6); ++ *m &= ~(1UL << (nr & 63)); ++} + +-extern __inline__ int test_bit(int nr, __const__ void *addr) ++static __inline__ void __change_bit(int nr, volatile void *addr) + { +- return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL; ++ unsigned long *m; ++ ++ m = ((unsigned long *)addr) + (nr >> 6); ++ *m ^= (1UL << (nr & 63)); ++} ++ ++static __inline__ int __test_and_set_bit(int nr, volatile void *addr) ++{ ++ unsigned long *m = ((unsigned long *)addr) + (nr >> 6); ++ unsigned long old = *m; ++ unsigned long mask = (1UL << (nr & 63)); ++ ++ *m = (old | mask); ++ return ((old & mask) != 0); ++} ++ ++static __inline__ int __test_and_clear_bit(int nr, volatile void *addr) ++{ ++ unsigned long *m = ((unsigned long *)addr) + (nr >> 6); ++ unsigned long old = *m; ++ unsigned long mask = (1UL << (nr & 63)); ++ ++ *m = (old & ~mask); ++ return ((old & mask) != 0); ++} ++ ++static __inline__ int __test_and_change_bit(int nr, volatile void *addr) ++{ ++ unsigned long *m = ((unsigned long *)addr) + (nr >> 6); ++ unsigned long old = *m; ++ unsigned long mask = (1UL << (nr & 63)); ++ ++ *m = (old ^ mask); ++ return ((old & mask) != 0); ++} ++ ++#ifdef CONFIG_SMP ++#define smp_mb__before_clear_bit() membar("#StoreLoad | #LoadLoad") ++#define smp_mb__after_clear_bit() membar("#StoreLoad | #StoreStore") ++#else ++#define smp_mb__before_clear_bit() barrier() ++#define smp_mb__after_clear_bit() barrier() ++#endif ++ ++static __inline__ int test_bit(int nr, __const__ volatile void *_addr) ++{ ++ __const__ unsigned long *addr; ++ ++ addr = (__const__ unsigned long *) _addr; ++ ++ return (1UL & ((addr)[nr >> 6] >> (nr & 63))) != 0UL; + } + + /* The easy/cheese version for now. */ +-extern __inline__ unsigned long ffz(unsigned long word) ++static __inline__ unsigned long ffz(unsigned long word) + { + unsigned long result; + +-#ifdef ULTRA_HAS_POPULATION_COUNT /* Thanks for nothing Sun... */ +- __asm__ __volatile__( +-" brz,pn %0, 1f\n" +-" neg %0, %%g1\n" +-" xnor %0, %%g1, %%g2\n" +-" popc %%g2, %0\n" +-"1: " : "=&r" (result) +- : "0" (word) +- : "g1", "g2"); +-#else +-#if 1 /* def EASY_CHEESE_VERSION */ + result = 0; + while(word & 1) { + result++; + word >>= 1; + } +-#else +- unsigned long tmp; ++ return result; ++} + +- result = 0; +- tmp = ~word & -~word; +- if (!(unsigned)tmp) { +- tmp >>= 32; +- result = 32; +- } +- if (!(unsigned short)tmp) { +- tmp >>= 16; +- result += 16; +- } +- if (!(unsigned char)tmp) { +- tmp >>= 8; +- result += 8; ++/** ++ * __ffs - find first bit in word. ++ * @word: The word to search ++ * ++ * Undefined if no bit exists, so code should check against 0 first. ++ */ ++static __inline__ unsigned long __ffs(unsigned long word) ++{ ++ unsigned long result = 0; ++ ++ while (!(word & 1UL)) { ++ result++; ++ word >>= 1; + } +- if (tmp & 0xf0) result += 4; +- if (tmp & 0xcc) result += 2; +- if (tmp & 0xaa) result ++; +-#endif +-#endif + return result; + } + ++/* ++ * fls: find last bit set. ++ */ ++ ++#define fls(x) generic_fls(x) ++ + #ifdef __KERNEL__ + + /* +@@ -122,8 +134,12 @@ + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +- +-#define ffs(x) generic_ffs(x) ++static __inline__ int ffs(int x) ++{ ++ if (!x) ++ return 0; ++ return __ffs((unsigned long)x) + 1; ++} + + /* + * hweightN: returns the hamming weight (i.e. the number +@@ -132,7 +148,15 @@ + + #ifdef ULTRA_HAS_POPULATION_COUNT + +-extern __inline__ unsigned int hweight32(unsigned int w) ++static __inline__ unsigned int hweight64(unsigned long w) ++{ ++ unsigned int res; ++ ++ __asm__ ("popc %1,%0" : "=r" (res) : "r" (w)); ++ return res; ++} ++ ++static __inline__ unsigned int hweight32(unsigned int w) + { + unsigned int res; + +@@ -140,7 +164,7 @@ + return res; + } + +-extern __inline__ unsigned int hweight16(unsigned int w) ++static __inline__ unsigned int hweight16(unsigned int w) + { + unsigned int res; + +@@ -148,7 +172,7 @@ + return res; + } + +-extern __inline__ unsigned int hweight8(unsigned int w) ++static __inline__ unsigned int hweight8(unsigned int w) + { + unsigned int res; + +@@ -158,6 +182,7 @@ + + #else + ++#define hweight64(x) generic_hweight64(x) + #define hweight32(x) generic_hweight32(x) + #define hweight16(x) generic_hweight16(x) + #define hweight8(x) generic_hweight8(x) +@@ -170,7 +195,7 @@ + * on Linus's ALPHA routines, which are pretty portable BTW. + */ + +-extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) ++static __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) + { + unsigned long *p = ((unsigned long *) addr) + (offset >> 6); + unsigned long result = offset & ~63UL; +@@ -211,15 +236,12 @@ + #define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) + +-extern long ___test_and_set_le_bit(int nr, volatile void *addr); +-extern long ___test_and_clear_le_bit(int nr, volatile void *addr); +- +-#define test_and_set_le_bit(nr,addr) ({___test_and_set_le_bit(nr,addr)!=0;}) +-#define test_and_clear_le_bit(nr,addr) ({___test_and_clear_le_bit(nr,addr)!=0;}) +-#define set_le_bit(nr,addr) ((void)___test_and_set_le_bit(nr,addr)) +-#define clear_le_bit(nr,addr) ((void)___test_and_clear_le_bit(nr,addr)) ++#define test_and_set_le_bit(nr,addr) \ ++ test_and_set_bit((nr) ^ 0x38, (addr)) ++#define test_and_clear_le_bit(nr,addr) \ ++ test_and_clear_bit((nr) ^ 0x38, (addr)) + +-extern __inline__ int test_le_bit(int nr, __const__ void * addr) ++static __inline__ int test_le_bit(int nr, __const__ void *addr) + { + int mask; + __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; +@@ -232,7 +254,7 @@ + #define find_first_zero_le_bit(addr, size) \ + find_next_zero_le_bit((addr), (size), 0) + +-extern __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset) ++static __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset) + { + unsigned long *p = ((unsigned long *) addr) + (offset >> 6); + unsigned long result = offset & ~63UL; +@@ -271,18 +293,41 @@ + + #ifdef __KERNEL__ + +-#define ext2_set_bit test_and_set_le_bit +-#define ext2_clear_bit test_and_clear_le_bit +-#define ext2_test_bit test_le_bit +-#define ext2_find_first_zero_bit find_first_zero_le_bit +-#define ext2_find_next_zero_bit find_next_zero_le_bit ++#define __set_le_bit(nr, addr) \ ++ __set_bit((nr) ^ 0x38, (addr)) ++#define __clear_le_bit(nr, addr) \ ++ __clear_bit((nr) ^ 0x38, (addr)) ++#define __test_and_clear_le_bit(nr, addr) \ ++ __test_and_clear_bit((nr) ^ 0x38, (addr)) ++#define __test_and_set_le_bit(nr, addr) \ ++ __test_and_set_bit((nr) ^ 0x38, (addr)) ++ ++#define ext2_set_bit(nr,addr) \ ++ __test_and_set_le_bit((nr),(unsigned long *)(addr)) ++#define ext2_set_bit_atomic(lock,nr,addr) \ ++ test_and_set_le_bit((nr),(unsigned long *)(addr)) ++#define ext2_clear_bit(nr,addr) \ ++ __test_and_clear_le_bit((nr),(unsigned long *)(addr)) ++#define ext2_clear_bit_atomic(lock,nr,addr) \ ++ test_and_clear_le_bit((nr),(unsigned long *)(addr)) ++#define ext2_test_bit(nr,addr) \ ++ test_le_bit((nr),(unsigned long *)(addr)) ++#define ext2_find_first_zero_bit(addr, size) \ ++ find_first_zero_le_bit((unsigned long *)(addr), (size)) ++#define ext2_find_next_zero_bit(addr, size, off) \ ++ find_next_zero_le_bit((unsigned long *)(addr), (size), (off)) + + /* Bitmap functions for the minix filesystem. */ +-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) +-#define minix_set_bit(nr,addr) set_bit(nr,addr) +-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +-#define minix_test_bit(nr,addr) test_bit(nr,addr) +-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) ++#define minix_test_and_set_bit(nr,addr) \ ++ test_and_set_bit((nr),(unsigned long *)(addr)) ++#define minix_set_bit(nr,addr) \ ++ set_bit((nr),(unsigned long *)(addr)) ++#define minix_test_and_clear_bit(nr,addr) \ ++ test_and_clear_bit((nr),(unsigned long *)(addr)) ++#define minix_test_bit(nr,addr) \ ++ test_bit((nr),(unsigned long *)(addr)) ++#define minix_find_first_zero_bit(addr,size) \ ++ find_first_zero_bit((unsigned long *)(addr),(size)) + + #endif /* __KERNEL__ */ + diff -Nur linux-2.4.29/include/asm-sparc64/param.h linux-mips/include/asm-sparc64/param.h --- linux-2.4.29/include/asm-sparc64/param.h 2000-10-30 23:34:12.000000000 +0100 +++ linux-mips/include/asm-sparc64/param.h 2000-11-23 03:00:56.000000000 +0100 @@ -24920,6 +37421,206 @@ diff -Nur linux-2.4.29/include/asm-sparc64/param.h linux-mips/include/asm-sparc6 #endif #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */ +diff -Nur linux-2.4.29/include/asm-sparc64/system.h linux-mips/include/asm-sparc64/system.h +--- linux-2.4.29/include/asm-sparc64/system.h 2003-06-13 16:51:38.000000000 +0200 ++++ linux-mips/include/asm-sparc64/system.h 2005-03-26 11:47:37.092563999 +0100 +@@ -106,9 +106,9 @@ + + #define nop() __asm__ __volatile__ ("nop") + +-#define membar(type) __asm__ __volatile__ ("membar " type : : : "memory"); ++#define membar(type) __asm__ __volatile__ ("membar " type : : : "memory") + #define mb() \ +- membar("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad"); ++ membar("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad") + #define rmb() membar("#LoadLoad") + #define wmb() membar("#StoreStore") + #define set_mb(__var, __value) \ +@@ -121,9 +121,9 @@ + #define smp_rmb() rmb() + #define smp_wmb() wmb() + #else +-#define smp_mb() __asm__ __volatile__("":::"memory"); +-#define smp_rmb() __asm__ __volatile__("":::"memory"); +-#define smp_wmb() __asm__ __volatile__("":::"memory"); ++#define smp_mb() __asm__ __volatile__("":::"memory") ++#define smp_rmb() __asm__ __volatile__("":::"memory") ++#define smp_wmb() __asm__ __volatile__("":::"memory") + #endif + + #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") +@@ -246,6 +246,7 @@ + extern __inline__ unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val) + { + __asm__ __volatile__( ++" membar #StoreLoad | #LoadLoad\n" + " mov %0, %%g5\n" + "1: lduw [%2], %%g7\n" + " cas [%2], %%g7, %0\n" +@@ -262,6 +263,7 @@ + extern __inline__ unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val) + { + __asm__ __volatile__( ++" membar #StoreLoad | #LoadLoad\n" + " mov %0, %%g5\n" + "1: ldx [%2], %%g7\n" + " casx [%2], %%g7, %0\n" +@@ -306,7 +308,8 @@ + extern __inline__ unsigned long + __cmpxchg_u32(volatile int *m, int old, int new) + { +- __asm__ __volatile__("cas [%2], %3, %0\n\t" ++ __asm__ __volatile__("membar #StoreLoad | #LoadLoad\n" ++ "cas [%2], %3, %0\n\t" + "membar #StoreLoad | #StoreStore" + : "=&r" (new) + : "0" (new), "r" (m), "r" (old) +@@ -318,7 +321,8 @@ + extern __inline__ unsigned long + __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) + { +- __asm__ __volatile__("casx [%2], %3, %0\n\t" ++ __asm__ __volatile__("membar #StoreLoad | #LoadLoad\n" ++ "casx [%2], %3, %0\n\t" + "membar #StoreLoad | #StoreStore" + : "=&r" (new) + : "0" (new), "r" (m), "r" (old) +diff -Nur linux-2.4.29/include/asm-x86_64/acpi.h linux-mips/include/asm-x86_64/acpi.h +--- linux-2.4.29/include/asm-x86_64/acpi.h 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/include/asm-x86_64/acpi.h 2005-03-26 11:47:37.164552184 +0100 +@@ -118,6 +118,7 @@ + extern int acpi_strict; + extern int acpi_disabled; + extern int acpi_ht; ++extern int acpi_skip_timer_override; + static inline void disable_acpi(void) + { + acpi_disabled = 1; +diff -Nur linux-2.4.29/include/linux/ata.h linux-mips/include/linux/ata.h +--- linux-2.4.29/include/linux/ata.h 2005-01-19 15:10:12.000000000 +0100 ++++ linux-mips/include/linux/ata.h 2005-03-26 11:47:37.226542010 +0100 +@@ -123,6 +123,8 @@ + ATA_CMD_PIO_WRITE_EXT = 0x34, + ATA_CMD_SET_FEATURES = 0xEF, + ATA_CMD_PACKET = 0xA0, ++ ATA_CMD_VERIFY = 0x40, ++ ATA_CMD_VERIFY_EXT = 0x42, + + /* SETFEATURES stuff */ + SETFEATURES_XFER = 0x03, +diff -Nur linux-2.4.29/include/linux/brlock.h linux-mips/include/linux/brlock.h +--- linux-2.4.29/include/linux/brlock.h 2002-11-29 00:53:15.000000000 +0100 ++++ linux-mips/include/linux/brlock.h 2005-03-26 11:47:37.233540861 +0100 +@@ -18,16 +18,6 @@ + * Registry idea and naming [ crutial! :-) ] by: + * + * David S. Miller <davem@redhat.com> +- * +- * David has an implementation that doesn't use atomic operations in +- * the read branch via memory ordering tricks - i guess we need to +- * split this up into a per-arch thing? The atomicity issue is a +- * secondary item in profiles, at least on x86 platforms. +- * +- * The atomic op version overhead is indeed a big deal on +- * load-locked/store-conditional cpus (ALPHA/MIPS/PPC) and +- * compare-and-swap cpus (Sparc64). So we control which +- * implementation to use with a __BRLOCK_USE_ATOMICS define. -DaveM + */ + + /* Register bigreader lock indices here. */ +@@ -45,17 +35,7 @@ + #include <linux/cache.h> + #include <linux/spinlock.h> + +-#if defined(__i386__) || defined(__ia64__) || defined(__x86_64__) +-#define __BRLOCK_USE_ATOMICS +-#else +-#undef __BRLOCK_USE_ATOMICS +-#endif +- +-#ifdef __BRLOCK_USE_ATOMICS +-typedef rwlock_t brlock_read_lock_t; +-#else + typedef unsigned int brlock_read_lock_t; +-#endif + + /* + * align last allocated index to the next cacheline: +@@ -65,39 +45,14 @@ + + extern brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX]; + +-#ifndef __BRLOCK_USE_ATOMICS + struct br_wrlock { + spinlock_t lock; + } __attribute__ ((__aligned__(SMP_CACHE_BYTES))); + + extern struct br_wrlock __br_write_locks[__BR_IDX_MAX]; +-#endif + + extern void __br_lock_usage_bug (void); + +-#ifdef __BRLOCK_USE_ATOMICS +- +-static inline void br_read_lock (enum brlock_indices idx) +-{ +- /* +- * This causes a link-time bug message if an +- * invalid index is used: +- */ +- if (idx >= __BR_END) +- __br_lock_usage_bug(); +- +- read_lock(&__brlock_array[smp_processor_id()][idx]); +-} +- +-static inline void br_read_unlock (enum brlock_indices idx) +-{ +- if (idx >= __BR_END) +- __br_lock_usage_bug(); +- +- read_unlock(&__brlock_array[smp_processor_id()][idx]); +-} +- +-#else /* ! __BRLOCK_USE_ATOMICS */ + static inline void br_read_lock (enum brlock_indices idx) + { + unsigned int *ctr; +@@ -149,7 +104,6 @@ + wmb(); + (*ctr)--; + } +-#endif /* __BRLOCK_USE_ATOMICS */ + + /* write path not inlined - it's rare and larger */ + +diff -Nur linux-2.4.29/include/linux/fs.h linux-mips/include/linux/fs.h +--- linux-2.4.29/include/linux/fs.h 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/include/linux/fs.h 2005-03-26 11:47:37.386515755 +0100 +@@ -576,6 +576,7 @@ + unsigned int f_uid, f_gid; + int f_error; + ++ size_t f_maxcount; + unsigned long f_version; + + /* needed for tty driver, and maybe others */ +@@ -1056,14 +1057,7 @@ + return 0; + } + +-static inline int locks_verify_area(int read_write, struct inode *inode, +- struct file *filp, loff_t offset, +- size_t count) +-{ +- if (inode->i_flock && MANDATORY_LOCK(inode)) +- return locks_mandatory_area(read_write, inode, filp, offset, count); +- return 0; +-} ++extern int rw_verify_area(int, struct file *, loff_t *, size_t); + + static inline int locks_verify_truncate(struct inode *inode, + struct file *filp, diff -Nur linux-2.4.29/include/linux/i2c-algo-au1550.h linux-mips/include/linux/i2c-algo-au1550.h --- linux-2.4.29/include/linux/i2c-algo-au1550.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips/include/linux/i2c-algo-au1550.h 2004-07-07 02:38:02.000000000 +0200 @@ -24977,6 +37678,229 @@ diff -Nur linux-2.4.29/include/linux/i2c-id.h linux-mips/include/linux/i2c-id.h /* --- SMBus only adapters */ #define I2C_HW_SMBUS_PIIX4 0x00 #define I2C_HW_SMBUS_ALI15X3 0x01 +diff -Nur linux-2.4.29/include/linux/jbd.h linux-mips/include/linux/jbd.h +--- linux-2.4.29/include/linux/jbd.h 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/include/linux/jbd.h 2005-03-26 11:47:37.416510832 +0100 +@@ -848,7 +848,7 @@ + + extern int log_space_left (journal_t *); /* Called with journal locked */ + extern tid_t log_start_commit (journal_t *, transaction_t *); +-extern void log_wait_commit (journal_t *, tid_t); ++extern int log_wait_commit (journal_t *, tid_t); + extern int log_do_checkpoint (journal_t *, int); + + extern void log_wait_for_space(journal_t *, int nblocks); +diff -Nur linux-2.4.29/include/linux/libata-compat.h linux-mips/include/linux/libata-compat.h +--- linux-2.4.29/include/linux/libata-compat.h 2005-01-19 15:10:12.000000000 +0100 ++++ linux-mips/include/linux/libata-compat.h 2005-03-26 11:47:37.456504268 +0100 +@@ -1,8 +1,16 @@ + #ifndef __LIBATA_COMPAT_H__ + #define __LIBATA_COMPAT_H__ + ++#include <linux/types.h> + #include <linux/delay.h> + #include <linux/pci.h> ++#include <linux/slab.h> ++ ++typedef u32 __le32; ++typedef u64 __le64; ++ ++#define DMA_64BIT_MASK 0xffffffffffffffffULL ++#define DMA_32BIT_MASK 0x00000000ffffffffULL + + #define MODULE_VERSION(ver_str) + +@@ -10,11 +18,6 @@ + struct pci_dev pdev; + }; + +-static inline void libata_msleep(unsigned long msecs) +-{ +- msleep(msecs); +-} +- + static inline struct pci_dev *to_pci_dev(struct device *dev) + { + return (struct pci_dev *) dev; +@@ -47,4 +50,13 @@ + #define dev_set_drvdata(dev,ptr) \ + pci_set_drvdata(to_pci_dev(dev),(ptr)) + ++static inline void *kcalloc(size_t nmemb, size_t size, int flags) ++{ ++ size_t total = nmemb * size; ++ void *mem = kmalloc(total, flags); ++ if (mem) ++ memset(mem, 0, total); ++ return mem; ++} ++ + #endif /* __LIBATA_COMPAT_H__ */ +diff -Nur linux-2.4.29/include/linux/libata.h linux-mips/include/linux/libata.h +--- linux-2.4.29/include/linux/libata.h 2005-01-19 15:10:12.000000000 +0100 ++++ linux-mips/include/linux/libata.h 2005-03-26 11:47:37.460503612 +0100 +@@ -335,6 +335,8 @@ + + void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); + u8 (*check_status)(struct ata_port *ap); ++ u8 (*check_altstatus)(struct ata_port *ap); ++ u8 (*check_err)(struct ata_port *ap); + void (*dev_select)(struct ata_port *ap, unsigned int device); + + void (*phy_reset) (struct ata_port *ap); +@@ -361,6 +363,9 @@ + void (*port_stop) (struct ata_port *ap); + + void (*host_stop) (struct ata_host_set *host_set); ++ ++ void (*bmdma_stop) (struct ata_port *ap); ++ u8 (*bmdma_status) (struct ata_port *ap); + }; + + struct ata_port_info { +@@ -401,6 +406,8 @@ + extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device); + extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); + extern u8 ata_check_status(struct ata_port *ap); ++extern u8 ata_altstatus(struct ata_port *ap); ++extern u8 ata_chk_err(struct ata_port *ap); + extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf); + extern int ata_port_start (struct ata_port *ap); + extern void ata_port_stop (struct ata_port *ap); +@@ -416,6 +423,8 @@ + unsigned int ofs, unsigned int len); + extern void ata_bmdma_setup (struct ata_queued_cmd *qc); + extern void ata_bmdma_start (struct ata_queued_cmd *qc); ++extern void ata_bmdma_stop(struct ata_port *ap); ++extern u8 ata_bmdma_status(struct ata_port *ap); + extern void ata_bmdma_irq_clear(struct ata_port *ap); + extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat); + extern void ata_eng_timeout(struct ata_port *ap); +@@ -435,8 +444,6 @@ + + extern struct ata_probe_ent * + ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port); +-extern struct ata_probe_ent * +-ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port); + extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); + + #endif /* CONFIG_PCI */ +@@ -453,26 +460,11 @@ + (dev->class == ATA_DEV_ATAPI)); + } + +-static inline u8 ata_chk_err(struct ata_port *ap) +-{ +- if (ap->flags & ATA_FLAG_MMIO) { +- return readb((void __iomem *) ap->ioaddr.error_addr); +- } +- return inb(ap->ioaddr.error_addr); +-} +- + static inline u8 ata_chk_status(struct ata_port *ap) + { + return ap->ops->check_status(ap); + } + +-static inline u8 ata_altstatus(struct ata_port *ap) +-{ +- if (ap->flags & ATA_FLAG_MMIO) +- return readb((void __iomem *)ap->ioaddr.altstatus_addr); +- return inb(ap->ioaddr.altstatus_addr); +-} +- + static inline void ata_pause(struct ata_port *ap) + { + ata_altstatus(ap); +@@ -596,46 +588,6 @@ + return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; + } + +-static inline void ata_bmdma_stop(struct ata_port *ap) +-{ +- if (ap->flags & ATA_FLAG_MMIO) { +- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; +- +- /* clear start/stop bit */ +- writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, +- mmio + ATA_DMA_CMD); +- } else { +- /* clear start/stop bit */ +- outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, +- ap->ioaddr.bmdma_addr + ATA_DMA_CMD); +- } +- +- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ +- ata_altstatus(ap); /* dummy read */ +-} +- +-static inline void ata_bmdma_ack_irq(struct ata_port *ap) +-{ +- if (ap->flags & ATA_FLAG_MMIO) { +- void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; +- writeb(readb(mmio), mmio); +- } else { +- unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; +- outb(inb(addr), addr); +- } +-} +- +-static inline u8 ata_bmdma_status(struct ata_port *ap) +-{ +- u8 host_stat; +- if (ap->flags & ATA_FLAG_MMIO) { +- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; +- host_stat = readb(mmio + ATA_DMA_STATUS); +- } else +- host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); +- return host_stat; +-} +- + static inline int ata_try_flush_cache(struct ata_device *dev) + { + return ata_id_wcache_enabled(dev->id) || +diff -Nur linux-2.4.29/include/linux/netfilter_ipv4/ip_conntrack.h linux-mips/include/linux/netfilter_ipv4/ip_conntrack.h +--- linux-2.4.29/include/linux/netfilter_ipv4/ip_conntrack.h 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/include/linux/netfilter_ipv4/ip_conntrack.h 2005-03-26 11:47:37.735458485 +0100 +@@ -249,10 +249,9 @@ + /* Call me when a conntrack is destroyed. */ + extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); + +-extern int ip_ct_no_defrag; + /* Returns new sk_buff, or NULL */ + struct sk_buff * +-ip_ct_gather_frags(struct sk_buff *skb); ++ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user); + + /* Delete all conntracks which match. */ + extern void +diff -Nur linux-2.4.29/include/linux/netlink.h linux-mips/include/linux/netlink.h +--- linux-2.4.29/include/linux/netlink.h 2005-01-19 15:10:12.000000000 +0100 ++++ linux-mips/include/linux/netlink.h 2005-03-26 11:47:37.463503119 +0100 +@@ -117,10 +117,9 @@ + + /* + * skb should fit one page. This choice is good for headerless malloc. +- * +- * FIXME: What is the best size for SLAB???? --ANK + */ +-#define NLMSG_GOODSIZE (PAGE_SIZE - ((sizeof(struct sk_buff)+0xF)&~0xF)) ++#define NLMSG_GOODORDER 0 ++#define NLMSG_GOODSIZE (SKB_MAX_ORDER(0, NLMSG_GOODORDER)) + + + struct netlink_callback +diff -Nur linux-2.4.29/include/linux/pci_ids.h linux-mips/include/linux/pci_ids.h +--- linux-2.4.29/include/linux/pci_ids.h 2005-01-19 15:10:12.000000000 +0100 ++++ linux-mips/include/linux/pci_ids.h 2005-03-26 11:47:37.534491468 +0100 +@@ -1937,7 +1937,6 @@ + #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 + #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 + #define PCI_DEVICE_ID_INTEL_82801EB_7 0x24d7 +-#define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca + #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db + #define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd + #define PCI_DEVICE_ID_INTEL_ESB_0 0x25a0 diff -Nur linux-2.4.29/include/linux/sched.h linux-mips/include/linux/sched.h --- linux-2.4.29/include/linux/sched.h 2005-01-19 15:10:12.000000000 +0100 +++ linux-mips/include/linux/sched.h 2004-11-29 18:47:18.000000000 +0100 @@ -25004,6 +37928,30 @@ diff -Nur linux-2.4.29/include/linux/serial.h linux-mips/include/linux/serial.h #define SERIAL_IO_PORT 0 #define SERIAL_IO_HUB6 1 +diff -Nur linux-2.4.29/include/linux/skbuff.h linux-mips/include/linux/skbuff.h +--- linux-2.4.29/include/linux/skbuff.h 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/include/linux/skbuff.h 2005-03-26 11:47:37.600480638 +0100 +@@ -290,15 +290,11 @@ + + static inline void kfree_skb(struct sk_buff *skb) + { +- if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users)) +- __kfree_skb(skb); +-} +- +-/* Use this if you didn't touch the skb state [for fast switching] */ +-static inline void kfree_skb_fast(struct sk_buff *skb) +-{ +- if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users)) +- kfree_skbmem(skb); ++ if (likely(atomic_read(&skb->users) == 1)) ++ smp_rmb(); ++ else if (likely(!atomic_dec_and_test(&skb->users))) ++ return; ++ __kfree_skb(skb); + } + + /** diff -Nur linux-2.4.29/include/linux/swap.h linux-mips/include/linux/swap.h --- linux-2.4.29/include/linux/swap.h 2005-01-19 15:10:12.000000000 +0100 +++ linux-mips/include/linux/swap.h 2004-11-29 18:47:18.000000000 +0100 @@ -25038,6 +37986,103 @@ diff -Nur linux-2.4.29/include/linux/swap.h linux-mips/include/linux/swap.h /* * Max bad pages in the new format.. */ +diff -Nur linux-2.4.29/include/linux/sysctl.h linux-mips/include/linux/sysctl.h +--- linux-2.4.29/include/linux/sysctl.h 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/include/linux/sysctl.h 2005-03-26 11:47:37.673468659 +0100 +@@ -326,6 +326,7 @@ + NET_TCP_BIC_LOW_WINDOW=104, + NET_TCP_DEFAULT_WIN_SCALE=105, + NET_TCP_MODERATE_RCVBUF=106, ++ NET_TCP_BIC_BETA=108, + }; + + enum { +diff -Nur linux-2.4.29/include/net/dst.h linux-mips/include/net/dst.h +--- linux-2.4.29/include/net/dst.h 2003-08-25 13:44:44.000000000 +0200 ++++ linux-mips/include/net/dst.h 2005-03-26 11:47:37.821444373 +0100 +@@ -104,8 +104,10 @@ + static inline + void dst_release(struct dst_entry * dst) + { +- if (dst) ++ if (dst) { ++ smp_mb__before_atomic_dec(); + atomic_dec(&dst->__refcnt); ++ } + } + + extern void * dst_alloc(struct dst_ops * ops); +diff -Nur linux-2.4.29/include/net/ip.h linux-mips/include/net/ip.h +--- linux-2.4.29/include/net/ip.h 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/include/net/ip.h 2005-03-26 11:47:37.822444209 +0100 +@@ -227,9 +227,19 @@ + /* + * Functions provided by ip_fragment.o + */ +- +-struct sk_buff *ip_defrag(struct sk_buff *skb); +-extern void ipfrag_flush(void); ++ ++enum ip_defrag_users ++{ ++ IP_DEFRAG_LOCAL_DELIVER, ++ IP_DEFRAG_CALL_RA_CHAIN, ++ IP_DEFRAG_CONNTRACK_IN, ++ IP_DEFRAG_CONNTRACK_OUT, ++ IP_DEFRAG_NAT_OUT, ++ IP_DEFRAG_VS_OUT, ++ IP_DEFRAG_VS_FWD ++}; ++ ++struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user); + extern int ip_frag_nqueues; + extern atomic_t ip_frag_mem; + +diff -Nur linux-2.4.29/include/net/tcp.h linux-mips/include/net/tcp.h +--- linux-2.4.29/include/net/tcp.h 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/include/net/tcp.h 2005-03-26 11:47:37.891432886 +0100 +@@ -395,9 +395,8 @@ + # define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG) + #endif + +-#define BICTCP_1_OVER_BETA 8 /* +- * Fast recovery +- * multiplicative decrease factor ++#define BICTCP_BETA_SCALE 1024 /* Scale factor beta calculation ++ * max_cwnd = snd_cwnd * beta + */ + #define BICTCP_MAX_INCREMENT 32 /* + * Limit on the amount of +@@ -491,6 +490,7 @@ + extern int sysctl_tcp_bic; + extern int sysctl_tcp_bic_fast_convergence; + extern int sysctl_tcp_bic_low_window; ++extern int sysctl_tcp_bic_beta; + extern int sysctl_tcp_default_win_scale; + extern int sysctl_tcp_moderate_rcvbuf; + +@@ -1132,15 +1132,16 @@ + if (tcp_is_bic(tp)) { + if (sysctl_tcp_bic_fast_convergence && + tp->snd_cwnd < tp->bictcp.last_max_cwnd) +- tp->bictcp.last_max_cwnd +- = (tp->snd_cwnd * (2*BICTCP_1_OVER_BETA-1)) +- / (BICTCP_1_OVER_BETA/2); ++ tp->bictcp.last_max_cwnd = (tp->snd_cwnd * ++ (BICTCP_BETA_SCALE ++ + sysctl_tcp_bic_beta)) ++ / (2 * BICTCP_BETA_SCALE); + else + tp->bictcp.last_max_cwnd = tp->snd_cwnd; + + if (tp->snd_cwnd > sysctl_tcp_bic_low_window) +- return max(tp->snd_cwnd - (tp->snd_cwnd/BICTCP_1_OVER_BETA), +- 2U); ++ return max((tp->snd_cwnd * sysctl_tcp_bic_beta) ++ / BICTCP_BETA_SCALE, 2U); + } + + return max(tp->snd_cwnd >> 1U, 2U); diff -Nur linux-2.4.29/include/video/newport.h linux-mips/include/video/newport.h --- linux-2.4.29/include/video/newport.h 2001-04-12 21:20:31.000000000 +0200 +++ linux-mips/include/video/newport.h 2004-09-23 15:32:29.000000000 +0200 @@ -25233,6 +38278,46 @@ diff -Nur linux-2.4.29/kernel/sys.c linux-mips/kernel/sys.c } /* +diff -Nur linux-2.4.29/lib/brlock.c linux-mips/lib/brlock.c +--- linux-2.4.29/lib/brlock.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/lib/brlock.c 2005-03-26 11:47:38.065404334 +0100 +@@ -15,29 +15,6 @@ + #include <linux/sched.h> + #include <linux/brlock.h> + +-#ifdef __BRLOCK_USE_ATOMICS +- +-brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX] = +- { [0 ... NR_CPUS-1] = { [0 ... __BR_IDX_MAX-1] = RW_LOCK_UNLOCKED } }; +- +-void fastcall __br_write_lock (enum brlock_indices idx) +-{ +- int i; +- +- for (i = 0; i < smp_num_cpus; i++) +- write_lock(&__brlock_array[cpu_logical_map(i)][idx]); +-} +- +-void fastcall __br_write_unlock (enum brlock_indices idx) +-{ +- int i; +- +- for (i = 0; i < smp_num_cpus; i++) +- write_unlock(&__brlock_array[cpu_logical_map(i)][idx]); +-} +- +-#else /* ! __BRLOCK_USE_ATOMICS */ +- + brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX] = + { [0 ... NR_CPUS-1] = { [0 ... __BR_IDX_MAX-1] = 0 } }; + +@@ -64,6 +41,4 @@ + spin_unlock(&__br_write_locks[idx].lock); + } + +-#endif /* __BRLOCK_USE_ATOMICS */ +- + #endif /* CONFIG_SMP */ diff -Nur linux-2.4.29/lib/Makefile linux-mips/lib/Makefile --- linux-2.4.29/lib/Makefile 2004-04-14 15:05:40.000000000 +0200 +++ linux-mips/lib/Makefile 2004-04-16 05:14:21.000000000 +0200 @@ -25244,3 +38329,712 @@ diff -Nur linux-2.4.29/lib/Makefile linux-mips/lib/Makefile include $(TOPDIR)/drivers/net/Makefile.lib include $(TOPDIR)/drivers/usb/Makefile.lib include $(TOPDIR)/drivers/bluetooth/Makefile.lib +diff -Nur linux-2.4.29/MAINTAINERS linux-mips/MAINTAINERS +--- linux-2.4.29/MAINTAINERS 2005-01-19 15:09:24.000000000 +0100 ++++ linux-mips/MAINTAINERS 2005-03-26 11:47:05.618729582 +0100 +@@ -1058,8 +1058,8 @@ + JFS FILESYSTEM + P: Dave Kleikamp + M: shaggy@austin.ibm.com +-L: jfs-discussion@oss.software.ibm.com +-W: http://oss.software.ibm.com/developerworks/opensource/jfs/ ++L: jfs-discussion@lists.sourceforge.net ++W: http://jfs.sourceforge.net/ + S: Supported + + JOYSTICK DRIVER +@@ -1532,7 +1532,7 @@ + + PPP OVER ETHERNET + P: Michal Ostrowski +-M: mostrows@styx.uwaterloo.ca ++M: mostrows@speakeasy.net + S: Maintained + + PRISM54 WIRELESS DRIVER +diff -Nur linux-2.4.29/Makefile linux-mips/Makefile +--- linux-2.4.29/Makefile 2005-01-19 15:10:14.000000000 +0100 ++++ linux-mips/Makefile 2005-03-26 11:47:05.686718424 +0100 +@@ -1,11 +1,11 @@ + VERSION = 2 + PATCHLEVEL = 4 +-SUBLEVEL = 29 +-EXTRAVERSION = ++SUBLEVEL = 30 ++EXTRAVERSION = -pre3 + + KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) + +-ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) ++ARCH = mips + KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") + + CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ +@@ -462,10 +462,11 @@ + $(MAKE) -C Documentation/DocBook mrproper + + distclean: mrproper +- rm -f core `find . \( -not -type d \) -and \ +- \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ +- -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ +- -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags ++ find . \( -not -type d \) -and \ ++ \( -name core -o -name '*.orig' -o -name '*.rej' \ ++ -o -name '*~' -o -name '*.bak' -o -name '#*#' \ ++ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \ ++ -o -name TAGS -o -name tags \) -print | env -i xargs rm -f + + backup: mrproper + cd .. && tar cf - linux/ | gzip -9 > backup.gz +@@ -492,7 +493,7 @@ + $(MAKE) -C Documentation/DocBook man + + sums: +- find . -type f -print | sort | xargs sum > .SUMS ++ find . -type f -print | sort | env -i xargs sum > .SUMS + + dep-files: scripts/mkdep archdep include/linux/version.h + rm -f .depend .hdepend +diff -Nur linux-2.4.29/mm/filemap.c linux-mips/mm/filemap.c +--- linux-2.4.29/mm/filemap.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/mm/filemap.c 2005-03-26 11:47:38.292367084 +0100 +@@ -1870,7 +1870,7 @@ + goto fput_in; + if (!in_inode->i_mapping->a_ops->readpage) + goto fput_in; +- retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count); ++ retval = rw_verify_area(READ, in_file, &in_file->f_pos, count); + if (retval) + goto fput_in; + +@@ -1887,7 +1887,7 @@ + if (!out_file->f_op || !out_file->f_op->write) + goto fput_out; + out_inode = out_file->f_dentry->d_inode; +- retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count); ++ retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count); + if (retval) + goto fput_out; + +@@ -2589,7 +2589,7 @@ + long error = -EBADF; + struct file * file; + struct inode * inode; +- unsigned long size, rlim_rss; ++ unsigned long size; + + /* Doesn't work if there's no mapped file. */ + if (!vma->vm_file) +@@ -2605,13 +2605,6 @@ + end = vma->vm_end; + end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + +- /* Make sure this doesn't exceed the process's max rss. */ +- error = -EIO; +- rlim_rss = current->rlim ? current->rlim[RLIMIT_RSS].rlim_cur : +- LONG_MAX; /* default: see resource.h */ +- if ((vma->vm_mm->rss + (end - start)) > rlim_rss) +- return error; +- + /* round to cluster boundaries if this isn't a "random" area. */ + if (!VM_RandomReadHint(vma)) { + start = CLUSTER_OFFSET(start); +@@ -3268,7 +3261,12 @@ + status = generic_osync_inode(inode, OSYNC_METADATA|OSYNC_DATA); + } + +- err = written ? written : status; ++ /* ++ * generic_osync_inode always returns 0 or negative value. ++ * So 'status < written' is always true, and written should ++ * be returned if status >= 0. ++ */ ++ err = (status < 0) ? status : written; + out: + + return err; +diff -Nur linux-2.4.29/mm/swapfile.c linux-mips/mm/swapfile.c +--- linux-2.4.29/mm/swapfile.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/mm/swapfile.c 2005-03-26 11:47:38.293366920 +0100 +@@ -738,8 +738,10 @@ + for (type = swap_list.head; type >= 0; type = swap_info[type].next) { + p = swap_info + type; + if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { +- if (p->swap_file == nd.dentry) +- break; ++ if (p->swap_file == nd.dentry || ++ (S_ISBLK(nd.dentry->d_inode->i_mode) && ++ p->swap_device == nd.dentry->d_inode->i_rdev)) ++ break; + } + prev = type; + } +diff -Nur linux-2.4.29/net/core/dev.c linux-mips/net/core/dev.c +--- linux-2.4.29/net/core/dev.c 2004-04-14 15:05:41.000000000 +0200 ++++ linux-mips/net/core/dev.c 2005-03-26 11:47:38.556323762 +0100 +@@ -2180,10 +2180,26 @@ + case SIOCSIFNAME: + if (dev->flags&IFF_UP) + return -EBUSY; +- if (__dev_get_by_name(ifr->ifr_newname)) +- return -EEXIST; +- memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ); +- dev->name[IFNAMSIZ-1] = 0; ++ /* Check if name contains a wildcard */ ++ if (strchr(ifr->ifr_newname, '%')) { ++ char format[IFNAMSIZ + 1]; ++ int ret; ++ memcpy(format, ifr->ifr_newname, IFNAMSIZ); ++ format[IFNAMSIZ-1] = 0; ++ /* Find a free name based on format. ++ * dev_alloc_name() replaces "%d" with at max ++ * 2 digits, so no name overflow. - Jean II */ ++ ret = dev_alloc_name(dev, format); ++ if (ret < 0) ++ return ret; ++ /* Copy the new name back to caller. */ ++ strncpy(ifr->ifr_newname, dev->name, IFNAMSIZ); ++ } else { ++ if (__dev_get_by_name(ifr->ifr_newname)) ++ return -EEXIST; ++ memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ); ++ dev->name[IFNAMSIZ-1] = 0; ++ } + notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); + return 0; + +@@ -2316,6 +2332,7 @@ + * - return a value + */ + ++ case SIOCSIFNAME: + case SIOCGMIIPHY: + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) +@@ -2351,7 +2368,6 @@ + case SIOCDELMULTI: + case SIOCSIFHWBROADCAST: + case SIOCSIFTXQLEN: +- case SIOCSIFNAME: + case SIOCSMIIREG: + case SIOCBONDENSLAVE: + case SIOCBONDRELEASE: +diff -Nur linux-2.4.29/net/core/dst.c linux-mips/net/core/dst.c +--- linux-2.4.29/net/core/dst.c 2003-08-25 13:44:44.000000000 +0200 ++++ linux-mips/net/core/dst.c 2005-03-26 11:47:38.557323598 +0100 +@@ -142,8 +142,13 @@ + + void dst_destroy(struct dst_entry * dst) + { +- struct neighbour *neigh = dst->neighbour; +- struct hh_cache *hh = dst->hh; ++ struct neighbour *neigh; ++ struct hh_cache *hh; ++ ++ smp_rmb(); ++ ++ neigh = dst->neighbour; ++ hh = dst->hh; + + dst->hh = NULL; + if (hh && atomic_dec_and_test(&hh->hh_refcnt)) +diff -Nur linux-2.4.29/net/core/neighbour.c linux-mips/net/core/neighbour.c +--- linux-2.4.29/net/core/neighbour.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/net/core/neighbour.c 2005-03-26 11:47:38.629311783 +0100 +@@ -111,7 +111,7 @@ + + unsigned long neigh_rand_reach_time(unsigned long base) + { +- return (net_random() % base) + (base>>1); ++ return (base ? (net_random() % base) + (base >> 1) : 0); + } + + +@@ -1469,6 +1469,7 @@ + + nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ndm)); + ndm = NLMSG_DATA(nlh); ++ nlh->nlmsg_flags = pid ? NLM_F_MULTI : 0; + ndm->ndm_family = n->ops->family; + ndm->ndm_flags = n->flags; + ndm->ndm_type = n->type; +diff -Nur linux-2.4.29/net/ipv4/ipconfig.c linux-mips/net/ipv4/ipconfig.c +--- linux-2.4.29/net/ipv4/ipconfig.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/net/ipv4/ipconfig.c 2005-03-26 11:47:38.712298163 +0100 +@@ -1162,7 +1162,7 @@ + if (*cp == ':') + *cp++ = '\0'; + addr = in_aton(name); +- strcpy(name, cp); ++ memmove(name, cp, strlen(cp) + 1); + } else + addr = INADDR_NONE; + +diff -Nur linux-2.4.29/net/ipv4/ip_fragment.c linux-mips/net/ipv4/ip_fragment.c +--- linux-2.4.29/net/ipv4/ip_fragment.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/net/ipv4/ip_fragment.c 2005-03-26 11:47:38.632311291 +0100 +@@ -72,6 +72,7 @@ + struct ipq { + struct ipq *next; /* linked list pointers */ + struct list_head lru_list; /* lru list member */ ++ u32 user; + u32 saddr; + u32 daddr; + u16 id; +@@ -242,13 +243,13 @@ + /* Memory limiting on fragments. Evictor trashes the oldest + * fragment queue until we are back under the threshold. + */ +-static void __ip_evictor(int threshold) ++static void ip_evictor(void) + { + struct ipq *qp; + struct list_head *tmp; + int work; + +- work = atomic_read(&ip_frag_mem) - threshold; ++ work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh; + if (work <= 0) + return; + +@@ -273,11 +274,6 @@ + } + } + +-static inline void ip_evictor(void) +-{ +- __ip_evictor(sysctl_ipfrag_low_thresh); +-} +- + /* + * Oops, a fragment queue timed out. Kill it and send an ICMP reply. + */ +@@ -324,7 +320,8 @@ + if(qp->id == qp_in->id && + qp->saddr == qp_in->saddr && + qp->daddr == qp_in->daddr && +- qp->protocol == qp_in->protocol) { ++ qp->protocol == qp_in->protocol && ++ qp->user == qp_in->user) { + atomic_inc(&qp->refcnt); + write_unlock(&ipfrag_lock); + qp_in->last_in |= COMPLETE; +@@ -351,7 +348,7 @@ + } + + /* Add an entry to the 'ipq' queue for a newly received IP datagram. */ +-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph) ++static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) + { + struct ipq *qp; + +@@ -363,6 +360,7 @@ + qp->id = iph->id; + qp->saddr = iph->saddr; + qp->daddr = iph->daddr; ++ qp->user = user; + qp->len = 0; + qp->meat = 0; + qp->fragments = NULL; +@@ -385,7 +383,7 @@ + /* Find the correct entry in the "incomplete datagrams" queue for + * this IP datagram, and create new one, if nothing is found. + */ +-static inline struct ipq *ip_find(struct iphdr *iph) ++static inline struct ipq *ip_find(struct iphdr *iph, u32 user) + { + __u16 id = iph->id; + __u32 saddr = iph->saddr; +@@ -399,7 +397,8 @@ + if(qp->id == id && + qp->saddr == saddr && + qp->daddr == daddr && +- qp->protocol == protocol) { ++ qp->protocol == protocol && ++ qp->user == user) { + atomic_inc(&qp->refcnt); + read_unlock(&ipfrag_lock); + return qp; +@@ -407,7 +406,7 @@ + } + read_unlock(&ipfrag_lock); + +- return ip_frag_create(hash, iph); ++ return ip_frag_create(hash, iph, user); + } + + /* Add new segment to existing queue. */ +@@ -641,7 +640,7 @@ + } + + /* Process an incoming IP datagram fragment. */ +-struct sk_buff *ip_defrag(struct sk_buff *skb) ++struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) + { + struct iphdr *iph = skb->nh.iph; + struct ipq *qp; +@@ -656,7 +655,7 @@ + dev = skb->dev; + + /* Lookup (or create) queue header */ +- if ((qp = ip_find(iph)) != NULL) { ++ if ((qp = ip_find(iph, user)) != NULL) { + struct sk_buff *ret = NULL; + + spin_lock(&qp->lock); +@@ -687,8 +686,3 @@ + ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval; + add_timer(&ipfrag_secret_timer); + } +- +-void ipfrag_flush(void) +-{ +- __ip_evictor(0); +-} +diff -Nur linux-2.4.29/net/ipv4/ip_input.c linux-mips/net/ipv4/ip_input.c +--- linux-2.4.29/net/ipv4/ip_input.c 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/net/ipv4/ip_input.c 2005-03-26 11:47:38.711298328 +0100 +@@ -170,7 +170,7 @@ + && ((sk->bound_dev_if == 0) + || (sk->bound_dev_if == skb->dev->ifindex))) { + if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { +- skb = ip_defrag(skb); ++ skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN); + if (skb == NULL) { + read_unlock(&ip_ra_lock); + return 1; +@@ -291,7 +291,7 @@ + */ + + if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { +- skb = ip_defrag(skb); ++ skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER); + if (!skb) + return 0; + } +diff -Nur linux-2.4.29/net/ipv4/ipvs/ip_vs_core.c linux-mips/net/ipv4/ipvs/ip_vs_core.c +--- linux-2.4.29/net/ipv4/ipvs/ip_vs_core.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/net/ipv4/ipvs/ip_vs_core.c 2005-03-26 11:47:38.913265180 +0100 +@@ -506,7 +506,7 @@ + + /* reassemble IP fragments, but will it happen in ICMP packets?? */ + if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) { +- skb = ip_defrag(skb); ++ skb = ip_defrag(skb, IP_DEFRAG_VS_OUT); + if (!skb) + return NF_STOLEN; + *skb_p = skb; +@@ -658,7 +658,7 @@ + + /* reassemble IP fragments */ + if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) { +- skb = ip_defrag(skb); ++ skb = ip_defrag(skb, IP_DEFRAG_VS_OUT); + if (!skb) + return NF_STOLEN; + iph = skb->nh.iph; +@@ -1164,7 +1164,7 @@ + return NF_ACCEPT; + + if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) { +- skb = ip_defrag(skb); ++ skb = ip_defrag(skb, IP_DEFRAG_VS_FWD); + if (!skb) + return NF_STOLEN; + *skb_p = skb; +diff -Nur linux-2.4.29/net/ipv4/netfilter/ip_conntrack_core.c linux-mips/net/ipv4/netfilter/ip_conntrack_core.c +--- linux-2.4.29/net/ipv4/netfilter/ip_conntrack_core.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/net/ipv4/netfilter/ip_conntrack_core.c 2005-03-26 11:47:38.949259273 +0100 +@@ -834,7 +834,10 @@ + + /* Gather fragments. */ + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { +- *pskb = ip_ct_gather_frags(*pskb); ++ *pskb = ip_ct_gather_frags(*pskb, ++ hooknum == NF_IP_PRE_ROUTING ? ++ IP_DEFRAG_CONNTRACK_IN : ++ IP_DEFRAG_CONNTRACK_OUT); + if (!*pskb) + return NF_STOLEN; + } +@@ -1183,29 +1186,22 @@ + WRITE_UNLOCK(&ip_conntrack_lock); + } + +-int ip_ct_no_defrag; +- + /* Returns new sk_buff, or NULL */ + struct sk_buff * +-ip_ct_gather_frags(struct sk_buff *skb) ++ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user) + { + struct sock *sk = skb->sk; + #ifdef CONFIG_NETFILTER_DEBUG + unsigned int olddebug = skb->nf_debug; + #endif + +- if (unlikely(ip_ct_no_defrag)) { +- kfree_skb(skb); +- return NULL; +- } +- + if (sk) { + sock_hold(sk); + skb_orphan(skb); + } + + local_bh_disable(); +- skb = ip_defrag(skb); ++ skb = ip_defrag(skb, user); + local_bh_enable(); + + if (!skb) { +diff -Nur linux-2.4.29/net/ipv4/netfilter/ip_conntrack_standalone.c linux-mips/net/ipv4/netfilter/ip_conntrack_standalone.c +--- linux-2.4.29/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-03-26 11:47:38.951258945 +0100 +@@ -393,13 +393,6 @@ + cleanup_inandlocalops: + nf_unregister_hook(&ip_conntrack_local_out_ops); + cleanup_inops: +- /* Frag queues may hold fragments with skb->dst == NULL */ +- ip_ct_no_defrag = 1; +- local_bh_disable(); +- br_write_lock(BR_NETPROTO_LOCK); +- br_write_unlock(BR_NETPROTO_LOCK); +- ipfrag_flush(); +- local_bh_enable(); + nf_unregister_hook(&ip_conntrack_in_ops); + cleanup_proc: + proc_net_remove("ip_conntrack"); +diff -Nur linux-2.4.29/net/ipv4/netfilter/ip_fw_compat.c linux-mips/net/ipv4/netfilter/ip_fw_compat.c +--- linux-2.4.29/net/ipv4/netfilter/ip_fw_compat.c 2003-11-28 19:26:21.000000000 +0100 ++++ linux-mips/net/ipv4/netfilter/ip_fw_compat.c 2005-03-26 11:47:38.979254350 +0100 +@@ -108,7 +108,7 @@ + (*pskb)->nh.raw, &redirpt, pskb); + + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { +- *pskb = ip_ct_gather_frags(*pskb); ++ *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_CONNTRACK_IN); + + if (!*pskb) + return NF_STOLEN; +diff -Nur linux-2.4.29/net/ipv4/netfilter/ip_nat_standalone.c linux-mips/net/ipv4/netfilter/ip_nat_standalone.c +--- linux-2.4.29/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/net/ipv4/netfilter/ip_nat_standalone.c 2005-03-26 11:47:38.980254186 +0100 +@@ -201,7 +201,7 @@ + I'm starting to have nightmares about fragments. */ + + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { +- *pskb = ip_ct_gather_frags(*pskb); ++ *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT); + + if (!*pskb) + return NF_STOLEN; +diff -Nur linux-2.4.29/net/ipv4/sysctl_net_ipv4.c linux-mips/net/ipv4/sysctl_net_ipv4.c +--- linux-2.4.29/net/ipv4/sysctl_net_ipv4.c 2004-08-08 01:26:06.000000000 +0200 ++++ linux-mips/net/ipv4/sysctl_net_ipv4.c 2005-03-26 11:47:38.713297999 +0100 +@@ -268,6 +268,9 @@ + {NET_TCP_MODERATE_RCVBUF, "tcp_moderate_rcvbuf", + &sysctl_tcp_moderate_rcvbuf, sizeof(int), 0644, NULL, + &proc_dointvec}, ++ {NET_TCP_BIC_BETA, "tcp_bic_beta", ++ &sysctl_tcp_bic_beta, sizeof(int), 0644, NULL, ++ &proc_dointvec}, + {0} + }; + +diff -Nur linux-2.4.29/net/ipv4/tcp_input.c linux-mips/net/ipv4/tcp_input.c +--- linux-2.4.29/net/ipv4/tcp_input.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-mips/net/ipv4/tcp_input.c 2005-03-26 11:47:38.911265508 +0100 +@@ -107,6 +107,7 @@ + int sysctl_tcp_bic; + int sysctl_tcp_bic_fast_convergence = 1; + int sysctl_tcp_bic_low_window = 14; ++int sysctl_tcp_bic_beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */ + + #define FLAG_DATA 0x01 /* Incoming frame contained data. */ + #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ +@@ -3647,8 +3648,7 @@ + while (before(start, end)) { + struct sk_buff *nskb; + int header = skb_headroom(skb); +- int copy = (PAGE_SIZE - sizeof(struct sk_buff) - +- sizeof(struct skb_shared_info) - header - 31)&~15; ++ int copy = SKB_MAX_ORDER(header, 0); + + /* Too big header? This can happen with IPv6. */ + if (copy < 0) +diff -Nur linux-2.4.29/net/netlink/af_netlink.c linux-mips/net/netlink/af_netlink.c +--- linux-2.4.29/net/netlink/af_netlink.c 2005-01-19 15:10:14.000000000 +0100 ++++ linux-mips/net/netlink/af_netlink.c 2005-03-26 11:47:39.200218085 +0100 +@@ -327,10 +327,11 @@ + struct sock **skp; + struct netlink_table *table = &nl_table[sk->protocol]; + struct nl_pid_hash *hash = &table->hash; ++ u32 pid = nlk_sk(sk)->pid; + + netlink_table_grab(); + hash->entries--; +- for (skp = hash->table; *skp; skp = &((*skp)->next)) { ++ for (skp = nl_pid_hashfn(hash, pid); *skp; skp = &((*skp)->next)) { + if (*skp == sk) { + *skp = sk->next; + __sock_put(sk); +diff -Nur linux-2.4.29/net/netsyms.c linux-mips/net/netsyms.c +--- linux-2.4.29/net/netsyms.c 2005-01-19 15:10:14.000000000 +0100 ++++ linux-mips/net/netsyms.c 2005-03-26 11:47:38.458339844 +0100 +@@ -287,7 +287,6 @@ + EXPORT_SYMBOL(inetdev_by_index); + EXPORT_SYMBOL(in_dev_finish_destroy); + EXPORT_SYMBOL(ip_defrag); +-EXPORT_SYMBOL(ipfrag_flush); + + /* Route manipulation */ + EXPORT_SYMBOL(ip_rt_ioctl); +diff -Nur linux-2.4.29/net/sched/cls_u32.c linux-mips/net/sched/cls_u32.c +--- linux-2.4.29/net/sched/cls_u32.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/net/sched/cls_u32.c 2005-03-26 11:47:39.202217756 +0100 +@@ -70,6 +70,7 @@ + { + struct tc_u_hnode *next; + u32 handle; ++ u32 prio; + struct tc_u_common *tp_c; + int refcnt; + unsigned divisor; +@@ -271,6 +272,7 @@ + root_ht->divisor = 0; + root_ht->refcnt++; + root_ht->handle = tp_c ? gen_new_htid(tp_c) : 0x80000000; ++ root_ht->prio = tp->prio; + + if (tp_c == NULL) { + tp_c = kmalloc(sizeof(*tp_c), GFP_KERNEL); +@@ -534,6 +536,7 @@ + ht->refcnt = 0; + ht->divisor = divisor; + ht->handle = handle; ++ ht->prio = tp->prio; + ht->next = tp_c->hlist; + tp_c->hlist = ht; + *arg = (unsigned long)ht; +@@ -606,6 +609,8 @@ + return; + + for (ht = tp_c->hlist; ht; ht = ht->next) { ++ if (ht->prio != tp->prio) ++ continue; + if (arg->count >= arg->skip) { + if (arg->fn(tp, (unsigned long)ht, arg) < 0) { + arg->stop = 1; +diff -Nur linux-2.4.29/net/sched/sch_ingress.c linux-mips/net/sched/sch_ingress.c +--- linux-2.4.29/net/sched/sch_ingress.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/net/sched/sch_ingress.c 2005-03-26 11:47:39.203217592 +0100 +@@ -14,6 +14,7 @@ + #include <linux/netdevice.h> + #include <linux/rtnetlink.h> + #include <linux/netfilter_ipv4.h> ++#include <linux/netfilter_ipv6.h> + #include <linux/netfilter.h> + #include <linux/smp.h> + #include <net/pkt_sched.h> +@@ -241,6 +242,15 @@ + NF_IP_PRI_FILTER + 1 + }; + ++static struct nf_hook_ops ing6_ops = ++{ ++ { NULL, NULL}, ++ ing_hook, ++ PF_INET6, ++ NF_IP6_PRE_ROUTING, ++ NF_IP6_PRI_FILTER + 1 ++}; ++ + int ingress_init(struct Qdisc *sch,struct rtattr *opt) + { + struct ingress_qdisc_data *p = PRIV(sch); +@@ -249,8 +259,13 @@ + if (nf_register_hook(&ing_ops) < 0) { + printk("ingress qdisc registration error \n"); + goto error; +- } ++ } + nf_registered++; ++ if (nf_register_hook(&ing6_ops) < 0) { ++ printk("IPv6 ingress qdisc registration error, " \ ++ "disabling IPv6 support.\n"); ++ } else ++ nf_registered++; + } + + DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); +@@ -374,8 +389,11 @@ + void cleanup_module(void) + { + unregister_qdisc(&ingress_qdisc_ops); +- if (nf_registered) ++ if (nf_registered) { + nf_unregister_hook(&ing_ops); ++ if (nf_registered > 1) ++ nf_unregister_hook(&ing6_ops); ++ } + } + #endif + MODULE_LICENSE("GPL"); +diff -Nur linux-2.4.29/net/sched/sch_netem.c linux-mips/net/sched/sch_netem.c +--- linux-2.4.29/net/sched/sch_netem.c 2005-01-19 15:10:14.000000000 +0100 ++++ linux-mips/net/sched/sch_netem.c 2005-03-26 11:47:39.283204465 +0100 +@@ -180,6 +180,7 @@ + if (q->loss && q->loss >= get_crandom(&q->loss_cor)) { + pr_debug("netem_enqueue: random loss\n"); + sch->stats.drops++; ++ kfree_skb(skb); + return 0; /* lie about loss so TCP doesn't know */ + } + +diff -Nur linux-2.4.29/net/unix/af_unix.c linux-mips/net/unix/af_unix.c +--- linux-2.4.29/net/unix/af_unix.c 2004-11-17 12:54:22.000000000 +0100 ++++ linux-mips/net/unix/af_unix.c 2005-03-26 11:47:39.318198721 +0100 +@@ -1686,8 +1686,13 @@ + } + + spin_lock(&sk->receive_queue.lock); +- if((skb=skb_peek(&sk->receive_queue))!=NULL) +- amount=skb->len; ++ if (sk->type == SOCK_STREAM) { ++ skb_queue_walk(&sk->receive_queue, skb) ++ amount += skb->len; ++ } else { ++ if((skb=skb_peek(&sk->receive_queue))!=NULL) ++ amount=skb->len; ++ } + spin_unlock(&sk->receive_queue.lock); + err = put_user(amount, (int *)arg); + break; +diff -Nur linux-2.4.29/scripts/Configure linux-mips/scripts/Configure +--- linux-2.4.29/scripts/Configure 2003-06-13 16:51:39.000000000 +0200 ++++ linux-mips/scripts/Configure 2005-03-26 11:47:39.412183296 +0100 +@@ -378,15 +378,18 @@ + function hex () { + old=$(eval echo "\${$2}") + def=${old:-$3} +- def=${def#*[x,X]} + while :; do + readln "$1 ($2) [$def] " "$def" "$old" +- ans=${ans#*[x,X]} +- if expr "$ans" : '[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then ++ if expr "$ans" : '0x[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then + define_hex "$2" "$ans" + break + else +- help "$2" ++ if expr "$ans" : '[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then ++ define_hex "$2" "0x$ans" ++ break ++ else ++ help "$2" ++ fi + fi + done + } diff --git a/package/linux/kernel-patches/302-ebtables b/package/linux/kernel-patches/302-ebtables index 27c5cb54c7..b1c34abe4d 100644 --- a/package/linux/kernel-patches/302-ebtables +++ b/package/linux/kernel-patches/302-ebtables @@ -1,7 +1,40 @@ -diff -Nur linux-mips-cvs/include/linux/if_bridge.h linux-ebtables/include/linux/if_bridge.h ---- linux-mips-cvs/include/linux/if_bridge.h 2000-02-24 01:13:20.000000000 +0100 -+++ linux-ebtables/include/linux/if_bridge.h 2005-02-07 05:52:50.000000000 +0100 -@@ -102,7 +102,8 @@ +--- linux-2.4.29/net/bridge/br_private.h 2004-08-08 01:26:06.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/net/bridge/br_private.h 2005-03-14 21:24:04.000000000 +0100 +@@ -143,8 +143,10 @@ extern void br_fdb_insert(struct net_bri + /* br_forward.c */ + extern void br_deliver(struct net_bridge_port *to, + struct sk_buff *skb); ++extern int br_dev_queue_push_xmit(struct sk_buff *skb); + extern void br_forward(struct net_bridge_port *to, + struct sk_buff *skb); ++extern int br_forward_finish(struct sk_buff *skb); + extern void br_flood_deliver(struct net_bridge *br, + struct sk_buff *skb, + int clone); +@@ -165,7 +167,8 @@ extern void br_get_port_ifindices(struct + int *ifindices); + + /* br_input.c */ +-extern void br_handle_frame(struct sk_buff *skb); ++extern int br_handle_frame_finish(struct sk_buff *skb); ++extern int br_handle_frame(struct sk_buff *skb); + + /* br_ioctl.c */ + extern int br_ioctl(struct net_bridge *br, +@@ -175,6 +178,10 @@ extern int br_ioctl(struct net_bridge *b + unsigned long arg2); + extern int br_ioctl_deviceless_stub(unsigned long arg); + ++/* br_netfilter.c */ ++extern int br_netfilter_init(void); ++extern void br_netfilter_fini(void); ++ + /* br_stp.c */ + extern int br_is_root_bridge(struct net_bridge *br); + extern struct net_bridge_port *br_get_port(struct net_bridge *br, +--- linux-2.4.29/include/linux/if_bridge.h 2001-11-22 20:47:12.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/if_bridge.h 2005-03-14 21:11:28.000000000 +0100 +@@ -102,7 +102,8 @@ struct net_bridge; struct net_bridge_port; extern int (*br_ioctl_hook)(unsigned long arg); @@ -11,876 +44,220 @@ diff -Nur linux-mips-cvs/include/linux/if_bridge.h linux-ebtables/include/linux/ #endif -diff -Nur linux-mips-cvs/include/linux/netfilter.h linux-ebtables/include/linux/netfilter.h ---- linux-mips-cvs/include/linux/netfilter.h 2005-01-20 03:19:24.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter.h 2005-02-07 05:52:50.000000000 +0100 -@@ -118,17 +118,23 @@ - /* This is gross, but inline doesn't cut it for avoiding the function - call in fast path: gcc doesn't inline (needs value tracking?). --RR */ - #ifdef CONFIG_NETFILTER_DEBUG --#define NF_HOOK nf_hook_slow -+#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \ -+nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN) -+#define NF_HOOK_THRESH nf_hook_slow - #else - #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \ - (list_empty(&nf_hooks[(pf)][(hook)]) \ - ? (okfn)(skb) \ -- : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn))) -+ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)) -+#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \ -+(list_empty(&nf_hooks[(pf)][(hook)]) \ -+ ? (okfn)(skb) \ -+ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh))) +--- linux-2.4.29/net/core/dev.c 2004-04-14 15:05:41.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/net/core/dev.c 2005-03-14 00:00:29.000000000 +0100 +@@ -1426,7 +1426,7 @@ static void net_tx_action(struct softirq + + + #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) +-void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; ++int (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; #endif - int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, - struct net_device *indev, struct net_device *outdev, -- int (*okfn)(struct sk_buff *)); -+ int (*okfn)(struct sk_buff *), int thresh); + static __inline__ int handle_bridge(struct sk_buff *skb, +@@ -1443,7 +1443,6 @@ static __inline__ int handle_bridge(stru + } + } - /* Call setsockopt() */ - int nf_setsockopt(struct sock *sk, int pf, int optval, char *opt, -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_802_3.h linux-ebtables/include/linux/netfilter_bridge/ebt_802_3.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_802_3.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_802_3.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,60 @@ -+#ifndef __LINUX_BRIDGE_EBT_802_3_H -+#define __LINUX_BRIDGE_EBT_802_3_H -+ -+#define EBT_802_3_SAP 0x01 -+#define EBT_802_3_TYPE 0x02 -+ -+#define EBT_802_3_MATCH "802_3" -+ -+/* -+ * If frame has DSAP/SSAP value 0xaa you must check the SNAP type -+ * to discover what kind of packet we're carrying. -+ */ -+#define CHECK_TYPE 0xaa -+ -+/* -+ * Control field may be one or two bytes. If the first byte has -+ * the value 0x03 then the entire length is one byte, otherwise it is two. -+ * One byte controls are used in Unnumbered Information frames. -+ * Two byte controls are used in Numbered Information frames. -+ */ -+#define IS_UI 0x03 -+ -+#define EBT_802_3_MASK (EBT_802_3_SAP | EBT_802_3_TYPE | EBT_802_3) -+ -+/* ui has one byte ctrl, ni has two */ -+struct hdr_ui { -+ uint8_t dsap; -+ uint8_t ssap; -+ uint8_t ctrl; -+ uint8_t orig[3]; -+ uint16_t type; -+}; -+ -+struct hdr_ni { -+ uint8_t dsap; -+ uint8_t ssap; -+ uint16_t ctrl; -+ uint8_t orig[3]; -+ uint16_t type; -+}; -+ -+struct ebt_802_3_hdr { -+ uint8_t daddr[6]; -+ uint8_t saddr[6]; -+ uint16_t len; -+ union { -+ struct hdr_ui ui; -+ struct hdr_ni ni; -+ } llc; -+}; -+ -+struct ebt_802_3_info -+{ -+ uint8_t sap; -+ uint16_t type; -+ uint8_t bitmask; -+ uint8_t invflags; -+}; -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_among.h linux-ebtables/include/linux/netfilter_bridge/ebt_among.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_among.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_among.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,65 @@ -+#ifndef __LINUX_BRIDGE_EBT_AMONG_H -+#define __LINUX_BRIDGE_EBT_AMONG_H -+ -+#define EBT_AMONG_DST 0x01 -+#define EBT_AMONG_SRC 0x02 -+ -+/* Grzegorz Borowiak <grzes@gnu.univ.gda.pl> 2003 -+ * -+ * Write-once-read-many hash table, used for checking if a given -+ * MAC address belongs to a set or not and possibly for checking -+ * if it is related with a given IPv4 address. -+ * -+ * The hash value of an address is its last byte. -+ * -+ * In real-world ethernet addresses, values of the last byte are -+ * evenly distributed and there is no need to consider other bytes. -+ * It would only slow the routines down. -+ * -+ * For MAC address comparison speedup reasons, we introduce a trick. -+ * MAC address is mapped onto an array of two 32-bit integers. -+ * This pair of integers is compared with MAC addresses in the -+ * hash table, which are stored also in form of pairs of integers -+ * (in `cmp' array). This is quick as it requires only two elementary -+ * number comparisons in worst case. Further, we take advantage of -+ * fact that entropy of 3 last bytes of address is larger than entropy -+ * of 3 first bytes. So first we compare 4 last bytes of addresses and -+ * if they are the same we compare 2 first. -+ * -+ * Yes, it is a memory overhead, but in 2003 AD, who cares? -+ */ -+ -+struct ebt_mac_wormhash_tuple -+{ -+ uint32_t cmp[2]; -+ uint32_t ip; -+}; -+ -+struct ebt_mac_wormhash -+{ -+ int table[257]; -+ int poolsize; -+ struct ebt_mac_wormhash_tuple pool[0]; -+}; -+ -+#define ebt_mac_wormhash_size(x) ((x) ? sizeof(struct ebt_mac_wormhash) \ -+ + (x)->poolsize * sizeof(struct ebt_mac_wormhash_tuple) : 0) -+ -+struct ebt_among_info -+{ -+ int wh_dst_ofs; -+ int wh_src_ofs; -+ int bitmask; -+}; -+ -+#define EBT_AMONG_DST_NEG 0x1 -+#define EBT_AMONG_SRC_NEG 0x2 -+ -+#define ebt_among_wh_dst(x) ((x)->wh_dst_ofs ? \ -+ (struct ebt_mac_wormhash*)((char*)(x) + (x)->wh_dst_ofs) : NULL) -+#define ebt_among_wh_src(x) ((x)->wh_src_ofs ? \ -+ (struct ebt_mac_wormhash*)((char*)(x) + (x)->wh_src_ofs) : NULL) -+ -+#define EBT_AMONG_MATCH "among" -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_arp.h linux-ebtables/include/linux/netfilter_bridge/ebt_arp.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_arp.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_arp.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,32 @@ -+#ifndef __LINUX_BRIDGE_EBT_ARP_H -+#define __LINUX_BRIDGE_EBT_ARP_H -+ -+#define EBT_ARP_OPCODE 0x01 -+#define EBT_ARP_HTYPE 0x02 -+#define EBT_ARP_PTYPE 0x04 -+#define EBT_ARP_SRC_IP 0x08 -+#define EBT_ARP_DST_IP 0x10 -+#define EBT_ARP_SRC_MAC 0x20 -+#define EBT_ARP_DST_MAC 0x40 -+#define EBT_ARP_MASK (EBT_ARP_OPCODE | EBT_ARP_HTYPE | EBT_ARP_PTYPE | \ -+ EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC) -+#define EBT_ARP_MATCH "arp" -+ -+struct ebt_arp_info -+{ -+ uint16_t htype; -+ uint16_t ptype; -+ uint16_t opcode; -+ uint32_t saddr; -+ uint32_t smsk; -+ uint32_t daddr; -+ uint32_t dmsk; -+ unsigned char smaddr[ETH_ALEN]; -+ unsigned char smmsk[ETH_ALEN]; -+ unsigned char dmaddr[ETH_ALEN]; -+ unsigned char dmmsk[ETH_ALEN]; -+ uint8_t bitmask; -+ uint8_t invflags; -+}; -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_arpreply.h linux-ebtables/include/linux/netfilter_bridge/ebt_arpreply.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_arpreply.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_arpreply.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,11 @@ -+#ifndef __LINUX_BRIDGE_EBT_ARPREPLY_H -+#define __LINUX_BRIDGE_EBT_ARPREPLY_H -+ -+struct ebt_arpreply_info -+{ -+ unsigned char mac[ETH_ALEN]; -+ int target; -+}; -+#define EBT_ARPREPLY_TARGET "arpreply" -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_ip.h linux-ebtables/include/linux/netfilter_bridge/ebt_ip.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_ip.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_ip.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,43 @@ -+/* -+ * ebt_ip -+ * -+ * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> -+ * -+ * April, 2002 -+ * -+ * Changes: -+ * added ip-sport and ip-dport -+ * Innominate Security Technologies AG <mhopf@innominate.com> -+ * September, 2002 -+ */ -+ -+#ifndef __LINUX_BRIDGE_EBT_IP_H -+#define __LINUX_BRIDGE_EBT_IP_H -+ -+#define EBT_IP_SOURCE 0x01 -+#define EBT_IP_DEST 0x02 -+#define EBT_IP_TOS 0x04 -+#define EBT_IP_PROTO 0x08 -+#define EBT_IP_SPORT 0x10 -+#define EBT_IP_DPORT 0x20 -+#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ -+ EBT_IP_SPORT | EBT_IP_DPORT ) -+#define EBT_IP_MATCH "ip" -+ -+// the same values are used for the invflags -+struct ebt_ip_info -+{ -+ uint32_t saddr; -+ uint32_t daddr; -+ uint32_t smsk; -+ uint32_t dmsk; -+ uint8_t tos; -+ uint8_t protocol; -+ uint8_t bitmask; -+ uint8_t invflags; -+ uint16_t sport[2]; -+ uint16_t dport[2]; -+}; -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_limit.h linux-ebtables/include/linux/netfilter_bridge/ebt_limit.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_limit.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_limit.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,23 @@ -+#ifndef __LINUX_BRIDGE_EBT_LIMIT_H -+#define __LINUX_BRIDGE_EBT_LIMIT_H -+ -+#define EBT_LIMIT_MATCH "limit" -+ -+/* timings are in milliseconds. */ -+#define EBT_LIMIT_SCALE 10000 -+ -+/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 -+ seconds, or one every 59 hours. */ -+ -+struct ebt_limit_info -+{ -+ u_int32_t avg; /* Average secs between packets * scale */ -+ u_int32_t burst; /* Period multiplier for upper limit. */ -+ -+ /* Used internally by the kernel */ -+ unsigned long prev; -+ u_int32_t credit; -+ u_int32_t credit_cap, cost; -+}; -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_log.h linux-ebtables/include/linux/netfilter_bridge/ebt_log.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_log.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_log.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,17 @@ -+#ifndef __LINUX_BRIDGE_EBT_LOG_H -+#define __LINUX_BRIDGE_EBT_LOG_H -+ -+#define EBT_LOG_IP 0x01 // if the frame is made by ip, log the ip information -+#define EBT_LOG_ARP 0x02 -+#define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP) -+#define EBT_LOG_PREFIX_SIZE 30 -+#define EBT_LOG_WATCHER "log" -+ -+struct ebt_log_info -+{ -+ uint8_t loglevel; -+ uint8_t prefix[EBT_LOG_PREFIX_SIZE]; -+ uint32_t bitmask; -+}; -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_mark_m.h linux-ebtables/include/linux/netfilter_bridge/ebt_mark_m.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_mark_m.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_mark_m.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,15 @@ -+#ifndef __LINUX_BRIDGE_EBT_MARK_M_H -+#define __LINUX_BRIDGE_EBT_MARK_M_H -+ -+#define EBT_MARK_AND 0x01 -+#define EBT_MARK_OR 0x02 -+#define EBT_MARK_MASK (EBT_MARK_AND | EBT_MARK_OR) -+struct ebt_mark_m_info -+{ -+ unsigned long mark, mask; -+ uint8_t invert; -+ uint8_t bitmask; -+}; -+#define EBT_MARK_MATCH "mark_m" -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_mark_t.h linux-ebtables/include/linux/netfilter_bridge/ebt_mark_t.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_mark_t.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_mark_t.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,12 @@ -+#ifndef __LINUX_BRIDGE_EBT_MARK_T_H -+#define __LINUX_BRIDGE_EBT_MARK_T_H -+ -+struct ebt_mark_t_info -+{ -+ unsigned long mark; -+ // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN -+ int target; -+}; -+#define EBT_MARK_TARGET "mark" -+ -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_nat.h linux-ebtables/include/linux/netfilter_bridge/ebt_nat.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_nat.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_nat.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,13 @@ -+#ifndef __LINUX_BRIDGE_EBT_NAT_H -+#define __LINUX_BRIDGE_EBT_NAT_H -+ -+struct ebt_nat_info -+{ -+ unsigned char mac[ETH_ALEN]; -+ // EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN -+ int target; -+}; -+#define EBT_SNAT_TARGET "snat" -+#define EBT_DNAT_TARGET "dnat" +- br_handle_frame_hook(skb); + return ret; + } + +@@ -1503,7 +1502,12 @@ int netif_receive_skb(struct sk_buff *sk + #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) + if (skb->dev->br_port != NULL && br_handle_frame_hook != NULL && + skb->pkt_type != PACKET_LOOPBACK) { +- return handle_bridge(skb, pt_prev); ++ int ret; + ++ ret = handle_bridge(skb, pt_prev); ++ if (br_handle_frame_hook(skb) == 0) ++ return ret; ++ pt_prev = NULL; + } + #endif + +--- linux-2.4.29/net/bridge/br_input.c 2003-08-25 13:44:44.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/net/bridge/br_input.c 2005-03-14 00:00:29.000000000 +0100 +@@ -24,6 +24,9 @@ unsigned char bridge_ula[6] = { 0x01, 0x + + static int br_pass_frame_up_finish(struct sk_buff *skb) + { ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug = 0; +#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_pkttype.h linux-ebtables/include/linux/netfilter_bridge/ebt_pkttype.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_pkttype.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_pkttype.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,11 @@ -+#ifndef __LINUX_BRIDGE_EBT_PKTTYPE_H -+#define __LINUX_BRIDGE_EBT_PKTTYPE_H + netif_rx(skb); + + return 0; +@@ -46,7 +49,7 @@ static void br_pass_frame_up(struct net_ + br_pass_frame_up_finish); + } + +-static int br_handle_frame_finish(struct sk_buff *skb) ++int br_handle_frame_finish(struct sk_buff *skb) + { + struct net_bridge *br; + unsigned char *dest; +@@ -112,7 +115,7 @@ err_nolock: + return 0; + } + +-void br_handle_frame(struct sk_buff *skb) ++int br_handle_frame(struct sk_buff *skb) + { + struct net_bridge *br; + unsigned char *dest; +@@ -146,26 +149,35 @@ void br_handle_frame(struct sk_buff *skb + goto handle_special_frame; + + if (p->state == BR_STATE_FORWARDING) { ++ if (br_should_route_hook && br_should_route_hook(&skb)) { ++ read_unlock(&br->lock); ++ return -1; ++ } + -+struct ebt_pkttype_info -+{ -+ uint8_t pkt_type; -+ uint8_t invert; -+}; -+#define EBT_PKTTYPE_MATCH "pkttype" ++ if (!memcmp(p->br->dev.dev_addr, dest, ETH_ALEN)) ++ skb->pkt_type = PACKET_HOST; + + NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, + br_handle_frame_finish); + read_unlock(&br->lock); +- return; ++ return 0; + } + + err: + read_unlock(&br->lock); + err_nolock: + kfree_skb(skb); +- return; ++ return 0; + + handle_special_frame: + if (!dest[5]) { + NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,NULL, + br_stp_handle_bpdu); + read_unlock(&br->lock); +- return; ++ return 0; + } + + read_unlock(&br->lock); + kfree_skb(skb); ++ return 0; + } +--- linux-2.4.29/net/bridge/br_forward.c 2003-11-28 19:26:21.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/br_forward.c 2005-03-14 00:00:29.000000000 +0100 +@@ -30,18 +30,21 @@ static inline int should_deliver(struct + return 1; + } + +-static int __dev_queue_push_xmit(struct sk_buff *skb) ++int br_dev_queue_push_xmit(struct sk_buff *skb) + { ++#ifdef CONFIG_NETFILTER ++ nf_bridge_maybe_copy_header(skb); +#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_redirect.h linux-ebtables/include/linux/netfilter_bridge/ebt_redirect.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_redirect.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_redirect.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,11 @@ -+#ifndef __LINUX_BRIDGE_EBT_REDIRECT_H -+#define __LINUX_BRIDGE_EBT_REDIRECT_H -+ -+struct ebt_redirect_info -+{ -+ // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN -+ int target; -+}; -+#define EBT_REDIRECT_TARGET "redirect" -+ + skb_push(skb, ETH_HLEN); + dev_queue_xmit(skb); + + return 0; + } + +-static int __br_forward_finish(struct sk_buff *skb) ++int br_forward_finish(struct sk_buff *skb) + { + NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev, +- __dev_queue_push_xmit); ++ br_dev_queue_push_xmit); + + return 0; + } +@@ -49,8 +52,11 @@ static int __br_forward_finish(struct sk + static void __br_deliver(struct net_bridge_port *to, struct sk_buff *skb) + { + skb->dev = to->dev; ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug = 0; +#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_stp.h linux-ebtables/include/linux/netfilter_bridge/ebt_stp.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_stp.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_stp.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,46 @@ -+#ifndef __LINUX_BRIDGE_EBT_STP_H -+#define __LINUX_BRIDGE_EBT_STP_H -+ -+#define EBT_STP_TYPE 0x0001 -+ -+#define EBT_STP_FLAGS 0x0002 -+#define EBT_STP_ROOTPRIO 0x0004 -+#define EBT_STP_ROOTADDR 0x0008 -+#define EBT_STP_ROOTCOST 0x0010 -+#define EBT_STP_SENDERPRIO 0x0020 -+#define EBT_STP_SENDERADDR 0x0040 -+#define EBT_STP_PORT 0x0080 -+#define EBT_STP_MSGAGE 0x0100 -+#define EBT_STP_MAXAGE 0x0200 -+#define EBT_STP_HELLOTIME 0x0400 -+#define EBT_STP_FWDD 0x0800 -+ -+#define EBT_STP_MASK 0x0fff -+#define EBT_STP_CONFIG_MASK 0x0ffe -+ -+#define EBT_STP_MATCH "stp" -+ -+struct ebt_stp_config_info -+{ -+ uint8_t flags; -+ uint16_t root_priol, root_priou; -+ char root_addr[6], root_addrmsk[6]; -+ uint32_t root_costl, root_costu; -+ uint16_t sender_priol, sender_priou; -+ char sender_addr[6], sender_addrmsk[6]; -+ uint16_t portl, portu; -+ uint16_t msg_agel, msg_ageu; -+ uint16_t max_agel, max_ageu; -+ uint16_t hello_timel, hello_timeu; -+ uint16_t forward_delayl, forward_delayu; -+}; -+ -+struct ebt_stp_info -+{ -+ uint8_t type; -+ struct ebt_stp_config_info config; -+ uint16_t bitmask; -+ uint16_t invflags; -+}; + NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, +- __br_forward_finish); ++ br_forward_finish); + } + + static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb) +@@ -62,7 +68,7 @@ static void __br_forward(struct net_brid + skb->ip_summed = CHECKSUM_NONE; + + NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, +- __br_forward_finish); ++ br_forward_finish); + } + + /* called under bridge lock */ +--- linux-2.4.29/net/bridge/br.c 2004-08-08 01:26:06.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/net/bridge/br.c 2005-03-14 00:00:29.000000000 +0100 +@@ -30,6 +30,8 @@ + #include "../atm/lec.h" + #endif + ++int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; + + void br_dec_use_count() + { + MOD_DEC_USE_COUNT; +@@ -44,6 +46,10 @@ static int __init br_init(void) + { + printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); + ++#ifdef CONFIG_NETFILTER ++ if (br_netfilter_init()) ++ return 1; +#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_ulog.h linux-ebtables/include/linux/netfilter_bridge/ebt_ulog.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_ulog.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_ulog.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,33 @@ -+#ifndef _EBT_ULOG_H -+#define _EBT_ULOG_H -+ -+#define EBT_ULOG_DEFAULT_NLGROUP 0 -+#define EBT_ULOG_DEFAULT_QTHRESHOLD 1 -+#define EBT_ULOG_MAXNLGROUPS 32 /* hardcoded netlink max */ -+#define EBT_ULOG_PREFIX_LEN 32 -+#define EBT_ULOG_MAX_QLEN 50 -+#define EBT_ULOG_WATCHER "ulog" -+ -+struct ebt_ulog_info { -+ uint32_t nlgroup; -+ unsigned int cprange; -+ unsigned int qthreshold; -+ char prefix[EBT_ULOG_PREFIX_LEN]; -+}; -+ -+typedef struct ebt_ulog_packet_msg { -+ char indev[IFNAMSIZ]; -+ char outdev[IFNAMSIZ]; -+ char physindev[IFNAMSIZ]; -+ char physoutdev[IFNAMSIZ]; -+ char prefix[EBT_ULOG_PREFIX_LEN]; -+ struct timeval stamp; -+ unsigned long mark; -+ unsigned int hook; -+ size_t data_len; -+ /* The complete packet, including Ethernet header and perhaps -+ * the VLAN header is appended */ -+ unsigned char data[0] __attribute__ ((aligned (__alignof__(int)))); -+} ebt_ulog_packet_msg_t; -+ -+#endif /* _EBT_ULOG_H */ -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebt_vlan.h linux-ebtables/include/linux/netfilter_bridge/ebt_vlan.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebt_vlan.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebt_vlan.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,20 @@ -+#ifndef __LINUX_BRIDGE_EBT_VLAN_H -+#define __LINUX_BRIDGE_EBT_VLAN_H -+ -+#define EBT_VLAN_ID 0x01 -+#define EBT_VLAN_PRIO 0x02 -+#define EBT_VLAN_ENCAP 0x04 -+#define EBT_VLAN_MASK (EBT_VLAN_ID | EBT_VLAN_PRIO | EBT_VLAN_ENCAP) -+#define EBT_VLAN_MATCH "vlan" -+ -+struct ebt_vlan_info { -+ uint16_t id; /* VLAN ID {1-4095} */ -+ uint8_t prio; /* VLAN User Priority {0-7} */ -+ uint16_t encap; /* VLAN Encapsulated frame code {0-65535} */ -+ uint8_t bitmask; /* Args bitmask bit 1=1 - ID arg, -+ bit 2=1 User-Priority arg, bit 3=1 encap*/ -+ uint8_t invflags; /* Inverse bitmask bit 1=1 - inversed ID arg, -+ bit 2=1 - inversed Pirority arg */ -+}; -+ + br_handle_frame_hook = br_handle_frame; + br_ioctl_hook = br_ioctl_deviceless_stub; + #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) +@@ -57,6 +63,9 @@ static int __init br_init(void) + + static void __exit br_deinit(void) + { ++#ifdef CONFIG_NETFILTER ++ br_netfilter_fini(); +#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge/ebtables.h linux-ebtables/include/linux/netfilter_bridge/ebtables.h ---- linux-mips-cvs/include/linux/netfilter_bridge/ebtables.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_bridge/ebtables.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,361 @@ -+/* -+ * ebtables -+ * -+ * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> -+ * -+ * ebtables.c,v 2.0, September, 2002 -+ * -+ * This code is stongly inspired on the iptables code which is -+ * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling -+ */ -+ -+#ifndef __LINUX_BRIDGE_EFF_H -+#define __LINUX_BRIDGE_EFF_H -+#include <linux/if.h> -+#include <linux/netfilter_bridge.h> -+#include <linux/if_ether.h> -+ -+#define EBT_TABLE_MAXNAMELEN 32 -+#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN -+#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN -+ -+// verdicts >0 are "branches" -+#define EBT_ACCEPT -1 -+#define EBT_DROP -2 -+#define EBT_CONTINUE -3 -+#define EBT_RETURN -4 -+#define NUM_STANDARD_TARGETS 4 -+ -+struct ebt_counter -+{ -+ uint64_t pcnt; -+ uint64_t bcnt; -+}; -+ -+struct ebt_entries { -+ // this field is always set to zero -+ // See EBT_ENTRY_OR_ENTRIES. -+ // Must be same size as ebt_entry.bitmask -+ unsigned int distinguisher; -+ // the chain name -+ char name[EBT_CHAIN_MAXNAMELEN]; -+ // counter offset for this chain -+ unsigned int counter_offset; -+ // one standard (accept, drop, return) per hook -+ int policy; -+ // nr. of entries -+ unsigned int nentries; -+ // entry list -+ char data[0]; -+}; -+ -+// used for the bitmask of struct ebt_entry -+ -+// This is a hack to make a difference between an ebt_entry struct and an -+// ebt_entries struct when traversing the entries from start to end. -+// Using this simplifies the code alot, while still being able to use -+// ebt_entries. -+// Contrary, iptables doesn't use something like ebt_entries and therefore uses -+// different techniques for naming the policy and such. So, iptables doesn't -+// need a hack like this. -+#define EBT_ENTRY_OR_ENTRIES 0x01 -+// these are the normal masks -+#define EBT_NOPROTO 0x02 -+#define EBT_802_3 0x04 -+#define EBT_SOURCEMAC 0x08 -+#define EBT_DESTMAC 0x10 -+#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \ -+ | EBT_ENTRY_OR_ENTRIES) -+ -+#define EBT_IPROTO 0x01 -+#define EBT_IIN 0x02 -+#define EBT_IOUT 0x04 -+#define EBT_ISOURCE 0x8 -+#define EBT_IDEST 0x10 -+#define EBT_ILOGICALIN 0x20 -+#define EBT_ILOGICALOUT 0x40 -+#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \ -+ | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST) -+ -+struct ebt_entry_match -+{ -+ union { -+ char name[EBT_FUNCTION_MAXNAMELEN]; -+ struct ebt_match *match; -+ } u; -+ // size of data -+ unsigned int match_size; -+ unsigned char data[0]; -+}; -+ -+struct ebt_entry_watcher -+{ -+ union { -+ char name[EBT_FUNCTION_MAXNAMELEN]; -+ struct ebt_watcher *watcher; -+ } u; -+ // size of data -+ unsigned int watcher_size; -+ unsigned char data[0]; -+}; -+ -+struct ebt_entry_target -+{ -+ union { -+ char name[EBT_FUNCTION_MAXNAMELEN]; -+ struct ebt_target *target; -+ } u; -+ // size of data -+ unsigned int target_size; -+ unsigned char data[0]; -+}; -+ -+#define EBT_STANDARD_TARGET "standard" -+struct ebt_standard_target -+{ -+ struct ebt_entry_target target; -+ int verdict; -+}; -+ -+// one entry -+struct ebt_entry { -+ // this needs to be the first field -+ unsigned int bitmask; -+ unsigned int invflags; -+ uint16_t ethproto; -+ // the physical in-dev -+ char in[IFNAMSIZ]; -+ // the logical in-dev -+ char logical_in[IFNAMSIZ]; -+ // the physical out-dev -+ char out[IFNAMSIZ]; -+ // the logical out-dev -+ char logical_out[IFNAMSIZ]; -+ unsigned char sourcemac[ETH_ALEN]; -+ unsigned char sourcemsk[ETH_ALEN]; -+ unsigned char destmac[ETH_ALEN]; -+ unsigned char destmsk[ETH_ALEN]; -+ // sizeof ebt_entry + matches -+ unsigned int watchers_offset; -+ // sizeof ebt_entry + matches + watchers -+ unsigned int target_offset; -+ // sizeof ebt_entry + matches + watchers + target -+ unsigned int next_offset; -+ unsigned char elems[0]; -+}; -+ -+struct ebt_replace -+{ -+ char name[EBT_TABLE_MAXNAMELEN]; -+ unsigned int valid_hooks; -+ // nr of rules in the table -+ unsigned int nentries; -+ // total size of the entries -+ unsigned int entries_size; -+ // start of the chains -+ struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; -+ // nr of counters userspace expects back -+ unsigned int num_counters; -+ // where the kernel will put the old counters -+ struct ebt_counter *counters; -+ char *entries; -+}; -+ -+// [gs]etsockopt numbers -+#define EBT_BASE_CTL 128 -+ -+#define EBT_SO_SET_ENTRIES (EBT_BASE_CTL) -+#define EBT_SO_SET_COUNTERS (EBT_SO_SET_ENTRIES+1) -+#define EBT_SO_SET_MAX (EBT_SO_SET_COUNTERS+1) -+ -+#define EBT_SO_GET_INFO (EBT_BASE_CTL) -+#define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1) -+#define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1) -+#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1) -+#define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1) -+ -+#ifdef __KERNEL__ -+ -+// return values for match() functions -+#define EBT_MATCH 0 -+#define EBT_NOMATCH 1 -+ -+struct ebt_match -+{ -+ struct list_head list; -+ const char name[EBT_FUNCTION_MAXNAMELEN]; -+ // 0 == it matches -+ int (*match)(const struct sk_buff *skb, const struct net_device *in, -+ const struct net_device *out, const void *matchdata, -+ unsigned int datalen); -+ // 0 == let it in -+ int (*check)(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *matchdata, unsigned int datalen); -+ void (*destroy)(void *matchdata, unsigned int datalen); -+ struct module *me; -+}; -+ -+struct ebt_watcher -+{ -+ struct list_head list; -+ const char name[EBT_FUNCTION_MAXNAMELEN]; -+ void (*watcher)(const struct sk_buff *skb, unsigned int hooknr, -+ const struct net_device *in, const struct net_device *out, -+ const void *watcherdata, unsigned int datalen); -+ // 0 == let it in -+ int (*check)(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *watcherdata, unsigned int datalen); -+ void (*destroy)(void *watcherdata, unsigned int datalen); -+ struct module *me; -+}; -+ -+struct ebt_target -+{ -+ struct list_head list; -+ const char name[EBT_FUNCTION_MAXNAMELEN]; -+ // returns one of the standard verdicts -+ int (*target)(struct sk_buff **pskb, unsigned int hooknr, -+ const struct net_device *in, const struct net_device *out, -+ const void *targetdata, unsigned int datalen); -+ // 0 == let it in -+ int (*check)(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *targetdata, unsigned int datalen); -+ void (*destroy)(void *targetdata, unsigned int datalen); -+ struct module *me; -+}; -+ -+// used for jumping from and into user defined chains (udc) -+struct ebt_chainstack -+{ -+ struct ebt_entries *chaininfo; // pointer to chain data -+ struct ebt_entry *e; // pointer to entry data -+ unsigned int n; // n'th entry -+}; -+ -+struct ebt_table_info -+{ -+ // total size of the entries -+ unsigned int entries_size; -+ unsigned int nentries; -+ // pointers to the start of the chains -+ struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; -+ // room to maintain the stack used for jumping from and into udc -+ struct ebt_chainstack **chainstack; -+ char *entries; -+ struct ebt_counter counters[0] ____cacheline_aligned; -+}; -+ -+struct ebt_table -+{ -+ struct list_head list; -+ char name[EBT_TABLE_MAXNAMELEN]; -+ struct ebt_replace *table; -+ unsigned int valid_hooks; -+ rwlock_t lock; -+ // e.g. could be the table explicitly only allows certain -+ // matches, targets, ... 0 == let it in -+ int (*check)(const struct ebt_table_info *info, -+ unsigned int valid_hooks); -+ // the data used by the kernel -+ struct ebt_table_info *private; -+}; -+ -+#define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_entry_target)-1)) & \ -+ ~(__alignof__(struct ebt_entry_target)-1)) -+extern int ebt_register_table(struct ebt_table *table); -+extern void ebt_unregister_table(struct ebt_table *table); -+extern int ebt_register_match(struct ebt_match *match); -+extern void ebt_unregister_match(struct ebt_match *match); -+extern int ebt_register_watcher(struct ebt_watcher *watcher); -+extern void ebt_unregister_watcher(struct ebt_watcher *watcher); -+extern int ebt_register_target(struct ebt_target *target); -+extern void ebt_unregister_target(struct ebt_target *target); -+extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ struct ebt_table *table); -+ -+ // Used in the kernel match() functions -+#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) -+// True if the hook mask denotes that the rule is in a base chain, -+// used in the check() functions -+#define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) -+// Clear the bit in the hook mask that tells if the rule is on a base chain -+#define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) -+// True if the target is not a standard target -+#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) -+ -+#endif /* __KERNEL__ */ -+ -+// blatently stolen from ip_tables.h -+// fn returns 0 to continue iteration -+#define EBT_MATCH_ITERATE(e, fn, args...) \ -+({ \ -+ unsigned int __i; \ -+ int __ret = 0; \ -+ struct ebt_entry_match *__match; \ -+ \ -+ for (__i = sizeof(struct ebt_entry); \ -+ __i < (e)->watchers_offset; \ -+ __i += __match->match_size + \ -+ sizeof(struct ebt_entry_match)) { \ -+ __match = (void *)(e) + __i; \ -+ \ -+ __ret = fn(__match , ## args); \ -+ if (__ret != 0) \ -+ break; \ -+ } \ -+ if (__ret == 0) { \ -+ if (__i != (e)->watchers_offset) \ -+ __ret = -EINVAL; \ -+ } \ -+ __ret; \ -+}) + unregister_netdevice_notifier(&br_device_notifier); + + rtnl_lock(); +@@ -73,7 +82,7 @@ static void __exit br_deinit(void) + #endif + } + +-EXPORT_NO_SYMBOLS; ++EXPORT_SYMBOL(br_should_route_hook); + + module_init(br_init) + module_exit(br_deinit) +--- linux-2.4.29/net/bridge/Makefile 2000-12-29 23:07:24.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/Makefile 2005-03-14 00:00:29.000000000 +0100 +@@ -7,10 +7,17 @@ + # + # Note 2! The CFLAGS definition is now in the main makefile... + ++export-objs := br.o + -+#define EBT_WATCHER_ITERATE(e, fn, args...) \ -+({ \ -+ unsigned int __i; \ -+ int __ret = 0; \ -+ struct ebt_entry_watcher *__watcher; \ -+ \ -+ for (__i = e->watchers_offset; \ -+ __i < (e)->target_offset; \ -+ __i += __watcher->watcher_size + \ -+ sizeof(struct ebt_entry_watcher)) { \ -+ __watcher = (void *)(e) + __i; \ -+ \ -+ __ret = fn(__watcher , ## args); \ -+ if (__ret != 0) \ -+ break; \ -+ } \ -+ if (__ret == 0) { \ -+ if (__i != (e)->target_offset) \ -+ __ret = -EINVAL; \ -+ } \ -+ __ret; \ -+}) + O_TARGET := bridge.o + obj-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \ + br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \ + br_stp_if.o br_stp_timer.o + -+#define EBT_ENTRY_ITERATE(entries, size, fn, args...) \ -+({ \ -+ unsigned int __i; \ -+ int __ret = 0; \ -+ struct ebt_entry *__entry; \ -+ \ -+ for (__i = 0; __i < (size);) { \ -+ __entry = (void *)(entries) + __i; \ -+ __ret = fn(__entry , ## args); \ -+ if (__ret != 0) \ -+ break; \ -+ if (__entry->bitmask != 0) \ -+ __i += __entry->next_offset; \ -+ else \ -+ __i += sizeof(struct ebt_entries); \ -+ } \ -+ if (__ret == 0) { \ -+ if (__i != (size)) \ -+ __ret = -EINVAL; \ -+ } \ -+ __ret; \ -+}) ++ifeq ($(CONFIG_NETFILTER),y) ++obj-y += br_netfilter.o ++endif + -+#endif -diff -Nur linux-mips-cvs/include/linux/netfilter_bridge.h linux-ebtables/include/linux/netfilter_bridge.h ---- linux-mips-cvs/include/linux/netfilter_bridge.h 2001-08-22 05:25:11.000000000 +0200 -+++ linux-ebtables/include/linux/netfilter_bridge.h 2005-02-07 05:52:50.000000000 +0100 + obj-m := $(O_TARGET) + + include $(TOPDIR)/Rules.make +--- linux-2.4.29/include/linux/netfilter_bridge.h 2001-06-12 04:15:27.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge.h 2005-03-14 21:24:06.000000000 +0100 @@ -6,6 +6,10 @@ #include <linux/config.h> @@ -970,1122 +347,41 @@ diff -Nur linux-mips-cvs/include/linux/netfilter_bridge.h linux-ebtables/include +#endif /* __KERNEL__ */ #endif -diff -Nur linux-mips-cvs/include/linux/netfilter_ipv4/ipt_physdev.h linux-ebtables/include/linux/netfilter_ipv4/ipt_physdev.h ---- linux-mips-cvs/include/linux/netfilter_ipv4/ipt_physdev.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_ipv4/ipt_physdev.h 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,24 @@ -+#ifndef _IPT_PHYSDEV_H -+#define _IPT_PHYSDEV_H -+ -+#ifdef __KERNEL__ -+#include <linux/if.h> -+#endif -+ -+#define IPT_PHYSDEV_OP_IN 0x01 -+#define IPT_PHYSDEV_OP_OUT 0x02 -+#define IPT_PHYSDEV_OP_BRIDGED 0x04 -+#define IPT_PHYSDEV_OP_ISIN 0x08 -+#define IPT_PHYSDEV_OP_ISOUT 0x10 -+#define IPT_PHYSDEV_OP_MASK (0x20 - 1) -+ -+struct ipt_physdev_info { -+ char physindev[IFNAMSIZ]; -+ char in_mask[IFNAMSIZ]; -+ char physoutdev[IFNAMSIZ]; -+ char out_mask[IFNAMSIZ]; -+ u_int8_t invert; -+ u_int8_t bitmask; -+}; -+ -+#endif /*_IPT_PHYSDEV_H*/ -diff -Nur linux-mips-cvs/include/linux/netfilter_ipv4.h linux-ebtables/include/linux/netfilter_ipv4.h ---- linux-mips-cvs/include/linux/netfilter_ipv4.h 2002-02-26 07:00:31.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_ipv4.h 2005-02-07 05:52:50.000000000 +0100 -@@ -52,8 +52,10 @@ - enum nf_ip_hook_priorities { - NF_IP_PRI_FIRST = INT_MIN, - NF_IP_PRI_CONNTRACK = -200, -+ NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175, - NF_IP_PRI_MANGLE = -150, - NF_IP_PRI_NAT_DST = -100, -+ NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50, - NF_IP_PRI_FILTER = 0, - NF_IP_PRI_NAT_SRC = 100, - NF_IP_PRI_LAST = INT_MAX, -diff -Nur linux-mips-cvs/include/linux/netfilter_ipv6.h linux-ebtables/include/linux/netfilter_ipv6.h ---- linux-mips-cvs/include/linux/netfilter_ipv6.h 2001-01-11 05:02:45.000000000 +0100 -+++ linux-ebtables/include/linux/netfilter_ipv6.h 2005-02-07 05:52:50.000000000 +0100 -@@ -57,8 +57,10 @@ - enum nf_ip6_hook_priorities { - NF_IP6_PRI_FIRST = INT_MIN, - NF_IP6_PRI_CONNTRACK = -200, -+ NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175, - NF_IP6_PRI_MANGLE = -150, - NF_IP6_PRI_NAT_DST = -100, -+ NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50, - NF_IP6_PRI_FILTER = 0, - NF_IP6_PRI_NAT_SRC = 100, - NF_IP6_PRI_LAST = INT_MAX, -diff -Nur linux-mips-cvs/include/linux/skbuff.h linux-ebtables/include/linux/skbuff.h ---- linux-mips-cvs/include/linux/skbuff.h 2005-01-31 12:56:47.000000000 +0100 -+++ linux-ebtables/include/linux/skbuff.h 2005-02-07 05:52:50.000000000 +0100 -@@ -92,6 +92,20 @@ - struct nf_ct_info { - struct nf_conntrack *master; - }; -+ -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+struct nf_bridge_info { -+ atomic_t use; -+ struct net_device *physindev; -+ struct net_device *physoutdev; -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+ struct net_device *netoutdev; -+#endif -+ unsigned int mask; -+ unsigned long data[32 / sizeof(unsigned long)]; -+}; -+#endif -+ - #endif +--- linux-2.4.29/include/linux/netfilter_ipv4/ip_tables.h 2004-08-08 01:26:06.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_ipv4/ip_tables.h 2005-03-14 21:24:28.000000000 +0100 +@@ -159,7 +159,7 @@ struct ipt_entry + #define IPT_CONTINUE 0xFFFFFFFF - struct sk_buff_head { -@@ -208,6 +222,9 @@ - #ifdef CONFIG_NETFILTER_DEBUG - unsigned int nf_debug; - #endif -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ struct nf_bridge_info *nf_bridge; /* Saved data about a bridged frame - see br_netfilter.c */ -+#endif - #endif /*CONFIG_NETFILTER*/ + /* For standard target */ +-#define IPT_RETURN (-NF_MAX_VERDICT - 1) ++#define IPT_RETURN (-NF_REPEAT - 1) - #if defined(CONFIG_HIPPI) -@@ -1175,6 +1192,20 @@ - skb->nf_debug = 0; - #endif - } -+ -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) -+{ -+ if (nf_bridge && atomic_dec_and_test(&nf_bridge->use)) -+ kfree(nf_bridge); -+} -+static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) -+{ -+ if (nf_bridge) -+ atomic_inc(&nf_bridge->use); -+} -+#endif -+ - #else /* CONFIG_NETFILTER */ - static inline void nf_reset(struct sk_buff *skb) {} - #endif /* CONFIG_NETFILTER */ -diff -Nur linux-mips-cvs/include/linux/sysctl.h linux-ebtables/include/linux/sysctl.h ---- linux-mips-cvs/include/linux/sysctl.h 2004-11-29 18:47:18.000000000 +0100 -+++ linux-ebtables/include/linux/sysctl.h 2005-02-07 05:52:50.000000000 +0100 -@@ -608,6 +608,15 @@ - NET_DECNET_CONF_DEV_STATE = 7 - }; + /* TCP matching stuff */ + struct ipt_tcp +--- linux-2.4.29/include/linux/netfilter_ipv6/ip6_tables.h 2004-08-08 01:26:06.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_ipv6/ip6_tables.h 2005-03-14 00:00:29.000000000 +0100 +@@ -167,7 +167,7 @@ struct ip6t_entry + #define IP6T_CONTINUE 0xFFFFFFFF -+/* /proc/sys/net/bridge */ -+enum { -+ NET_BRIDGE_NF_CALL_ARPTABLES = 1, -+ NET_BRIDGE_NF_CALL_IPTABLES = 2, -+ NET_BRIDGE_NF_CALL_IP6TABLES = 3, -+ NET_BRIDGE_NF_FILTER_VLAN_TAGGED = 4, -+}; -+ -+ - /* CTL_PROC names: */ + /* For standard target */ +-#define IP6T_RETURN (-NF_MAX_VERDICT - 1) ++#define IP6T_RETURN (-NF_REPEAT - 1) - /* CTL_FS names: */ -diff -Nur linux-mips-cvs/include/linux/sysctl.h.orig linux-ebtables/include/linux/sysctl.h.orig ---- linux-mips-cvs/include/linux/sysctl.h.orig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/include/linux/sysctl.h.orig 2004-11-29 18:47:18.000000000 +0100 -@@ -0,0 +1,841 @@ -+/* -+ * sysctl.h: General linux system control interface -+ * -+ * Begun 24 March 1995, Stephen Tweedie -+ * -+ **************************************************************** -+ **************************************************************** -+ ** -+ ** WARNING: -+ ** The values in this file are exported to user space via -+ ** the sysctl() binary interface. Do *NOT* change the -+ ** numbering of any existing values here, and do not change -+ ** any numbers within any one set of values. If you have -+ ** to redefine an existing interface, use a new number for it. -+ ** The kernel will then return ENOTDIR to any application using -+ ** the old binary interface. -+ ** -+ ** --sct -+ ** -+ **************************************************************** -+ **************************************************************** -+ */ -+ -+#ifndef _LINUX_SYSCTL_H -+#define _LINUX_SYSCTL_H -+ -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/list.h> -+ -+struct file; -+ -+#define CTL_MAXNAME 10 -+ -+struct __sysctl_args { -+ int *name; -+ int nlen; -+ void *oldval; -+ size_t *oldlenp; -+ void *newval; -+ size_t newlen; -+ unsigned long __unused[4]; -+}; -+ -+/* Define sysctl names first */ -+ -+/* Top-level names: */ -+ -+/* For internal pattern-matching use only: */ -+#ifdef __KERNEL__ -+#define CTL_ANY -1 /* Matches any name */ -+#define CTL_NONE 0 -+#endif -+ -+enum -+{ -+ CTL_KERN=1, /* General kernel info and control */ -+ CTL_VM=2, /* VM management */ -+ CTL_NET=3, /* Networking */ -+ CTL_PROC=4, /* Process info */ -+ CTL_FS=5, /* Filesystems */ -+ CTL_DEBUG=6, /* Debugging */ -+ CTL_DEV=7, /* Devices */ -+ CTL_BUS=8, /* Busses */ -+ CTL_ABI=9, /* Binary emulation */ -+ CTL_CPU=10 /* CPU stuff (speed scaling, etc) */ -+}; -+ -+/* CTL_BUS names: */ -+enum -+{ -+ CTL_BUS_ISA=1 /* ISA */ -+}; -+ -+/* CTL_KERN names: */ -+enum -+{ -+ KERN_OSTYPE=1, /* string: system version */ -+ KERN_OSRELEASE=2, /* string: system release */ -+ KERN_OSREV=3, /* int: system revision */ -+ KERN_VERSION=4, /* string: compile time info */ -+ KERN_SECUREMASK=5, /* struct: maximum rights mask */ -+ KERN_PROF=6, /* table: profiling information */ -+ KERN_NODENAME=7, -+ KERN_DOMAINNAME=8, -+ -+ KERN_CAP_BSET=14, /* int: capability bounding set */ -+ KERN_PANIC=15, /* int: panic timeout */ -+ KERN_REALROOTDEV=16, /* real root device to mount after initrd */ -+ -+ KERN_SPARC_REBOOT=21, /* reboot command on Sparc */ -+ KERN_CTLALTDEL=22, /* int: allow ctl-alt-del to reboot */ -+ KERN_PRINTK=23, /* struct: control printk logging parameters */ -+ KERN_NAMETRANS=24, /* Name translation */ -+ KERN_PPC_HTABRECLAIM=25, /* turn htab reclaimation on/off on PPC */ -+ KERN_PPC_ZEROPAGED=26, /* turn idle page zeroing on/off on PPC */ -+ KERN_PPC_POWERSAVE_NAP=27, /* use nap mode for power saving */ -+ KERN_MODPROBE=28, -+ KERN_SG_BIG_BUFF=29, -+ KERN_ACCT=30, /* BSD process accounting parameters */ -+ KERN_PPC_L2CR=31, /* l2cr register on PPC */ -+ -+ KERN_RTSIGNR=32, /* Number of rt sigs queued */ -+ KERN_RTSIGMAX=33, /* Max queuable */ -+ -+ KERN_SHMMAX=34, /* long: Maximum shared memory segment */ -+ KERN_MSGMAX=35, /* int: Maximum size of a messege */ -+ KERN_MSGMNB=36, /* int: Maximum message queue size */ -+ KERN_MSGPOOL=37, /* int: Maximum system message pool size */ -+ KERN_SYSRQ=38, /* int: Sysreq enable */ -+ KERN_MAX_THREADS=39, /* int: Maximum nr of threads in the system */ -+ KERN_RANDOM=40, /* Random driver */ -+ KERN_SHMALL=41, /* int: Maximum size of shared memory */ -+ KERN_MSGMNI=42, /* int: msg queue identifiers */ -+ KERN_SEM=43, /* struct: sysv semaphore limits */ -+ KERN_SPARC_STOP_A=44, /* int: Sparc Stop-A enable */ -+ KERN_SHMMNI=45, /* int: shm array identifiers */ -+ KERN_OVERFLOWUID=46, /* int: overflow UID */ -+ KERN_OVERFLOWGID=47, /* int: overflow GID */ -+ KERN_SHMPATH=48, /* string: path to shm fs */ -+ KERN_HOTPLUG=49, /* string: path to hotplug policy agent */ -+ KERN_IEEE_EMULATION_WARNINGS=50, /* int: unimplemented ieee instructions */ -+ KERN_S390_USER_DEBUG_LOGGING=51, /* int: dumps of user faults */ -+ KERN_CORE_USES_PID=52, /* int: use core or core.%pid */ -+ KERN_TAINTED=53, /* int: various kernel tainted flags */ -+ KERN_CADPID=54, /* int: PID of the process to notify on CAD */ -+ KERN_CORE_PATTERN=56, /* string: pattern for core-files */ -+ KERN_PPC_L3CR=57, /* l3cr register on PPC */ -+ KERN_EXCEPTION_TRACE=58, /* boolean: exception trace */ -+ KERN_CORE_SETUID=59, /* int: set to allow core dumps of setuid apps */ -+ KERN_SPARC_SCONS_PWROFF=64, /* int: serial console power-off halt */ -+}; -+ -+ -+/* CTL_VM names: */ -+enum -+{ -+ VM_SWAPCTL=1, /* struct: Set vm swapping control */ -+ VM_SWAPOUT=2, /* int: Linear or sqrt() swapout for hogs */ -+ VM_FREEPG=3, /* struct: Set free page thresholds */ -+ VM_BDFLUSH=4, /* struct: Control buffer cache flushing */ -+ VM_OVERCOMMIT_MEMORY=5, /* Turn off the virtual memory safety limit */ -+ VM_BUFFERMEM=6, /* struct: Set buffer memory thresholds */ -+ VM_PAGECACHE=7, /* struct: Set cache memory thresholds */ -+ VM_PAGERDAEMON=8, /* struct: Control kswapd behaviour */ -+ VM_PGT_CACHE=9, /* struct: Set page table cache parameters */ -+ VM_PAGE_CLUSTER=10, /* int: set number of pages to swap together */ -+ VM_MAX_MAP_COUNT=11, /* int: Maximum number of active map areas */ -+ VM_MIN_READAHEAD=12, /* Min file readahead */ -+ VM_MAX_READAHEAD=13, /* Max file readahead */ -+ VM_VFS_SCAN_RATIO=14, /* part of the inactive vfs lists to scan */ -+ VM_LRU_BALANCE_RATIO=15,/* balance active and inactive caches */ -+ VM_PASSES=16, /* number of vm passes before failing */ -+ VM_PAGEBUF=17, /* struct: Control pagebuf parameters */ -+ VM_GFP_DEBUG=18, /* debug GFP failures */ -+ VM_CACHE_SCAN_RATIO=19, /* part of the inactive cache list to scan */ -+ VM_MAPPED_RATIO=20, /* amount of unfreeable pages that triggers swapout */ -+ VM_LAPTOP_MODE=21, /* kernel in laptop flush mode */ -+ VM_BLOCK_DUMP=22, /* dump fs activity to log */ -+ VM_ANON_LRU=23, /* immediatly insert anon pages in the vm page lru */ -+}; -+ -+ -+/* CTL_NET names: */ -+enum -+{ -+ NET_CORE=1, -+ NET_ETHER=2, -+ NET_802=3, -+ NET_UNIX=4, -+ NET_IPV4=5, -+ NET_IPX=6, -+ NET_ATALK=7, -+ NET_NETROM=8, -+ NET_AX25=9, -+ NET_BRIDGE=10, -+ NET_ROSE=11, -+ NET_IPV6=12, -+ NET_X25=13, -+ NET_TR=14, -+ NET_DECNET=15, -+ NET_ECONET=16, -+ NET_KHTTPD=17, -+ NET_SCTP=18 -+}; -+ -+/* /proc/sys/kernel/random */ -+enum -+{ -+ RANDOM_POOLSIZE=1, -+ RANDOM_ENTROPY_COUNT=2, -+ RANDOM_READ_THRESH=3, -+ RANDOM_WRITE_THRESH=4, -+ RANDOM_BOOT_ID=5, -+ RANDOM_UUID=6 -+}; -+ -+/* /proc/sys/bus/isa */ -+enum -+{ -+ BUS_ISA_MEM_BASE=1, -+ BUS_ISA_PORT_BASE=2, -+ BUS_ISA_PORT_SHIFT=3 -+}; -+ -+/* /proc/sys/net/core */ -+enum -+{ -+ NET_CORE_WMEM_MAX=1, -+ NET_CORE_RMEM_MAX=2, -+ NET_CORE_WMEM_DEFAULT=3, -+ NET_CORE_RMEM_DEFAULT=4, -+/* was NET_CORE_DESTROY_DELAY */ -+ NET_CORE_MAX_BACKLOG=6, -+ NET_CORE_FASTROUTE=7, -+ NET_CORE_MSG_COST=8, -+ NET_CORE_MSG_BURST=9, -+ NET_CORE_OPTMEM_MAX=10, -+ NET_CORE_HOT_LIST_LENGTH=11, -+ NET_CORE_DIVERT_VERSION=12, -+ NET_CORE_NO_CONG_THRESH=13, -+ NET_CORE_NO_CONG=14, -+ NET_CORE_LO_CONG=15, -+ NET_CORE_MOD_CONG=16, -+ NET_CORE_DEV_WEIGHT=17, -+ NET_CORE_SOMAXCONN=18, -+}; -+ -+/* /proc/sys/net/ethernet */ -+ -+/* /proc/sys/net/802 */ -+ -+/* /proc/sys/net/unix */ -+ -+enum -+{ -+ NET_UNIX_DESTROY_DELAY=1, -+ NET_UNIX_DELETE_DELAY=2, -+ NET_UNIX_MAX_DGRAM_QLEN=3, -+}; -+ -+/* /proc/sys/net/ipv4 */ -+enum -+{ -+ /* v2.0 compatibile variables */ -+ NET_IPV4_FORWARD=8, -+ NET_IPV4_DYNADDR=9, -+ -+ NET_IPV4_CONF=16, -+ NET_IPV4_NEIGH=17, -+ NET_IPV4_ROUTE=18, -+ NET_IPV4_FIB_HASH=19, -+ NET_IPV4_NETFILTER=20, -+ -+ NET_IPV4_TCP_TIMESTAMPS=33, -+ NET_IPV4_TCP_WINDOW_SCALING=34, -+ NET_IPV4_TCP_SACK=35, -+ NET_IPV4_TCP_RETRANS_COLLAPSE=36, -+ NET_IPV4_DEFAULT_TTL=37, -+ NET_IPV4_AUTOCONFIG=38, -+ NET_IPV4_NO_PMTU_DISC=39, -+ NET_IPV4_TCP_SYN_RETRIES=40, -+ NET_IPV4_IPFRAG_HIGH_THRESH=41, -+ NET_IPV4_IPFRAG_LOW_THRESH=42, -+ NET_IPV4_IPFRAG_TIME=43, -+ NET_IPV4_TCP_MAX_KA_PROBES=44, -+ NET_IPV4_TCP_KEEPALIVE_TIME=45, -+ NET_IPV4_TCP_KEEPALIVE_PROBES=46, -+ NET_IPV4_TCP_RETRIES1=47, -+ NET_IPV4_TCP_RETRIES2=48, -+ NET_IPV4_TCP_FIN_TIMEOUT=49, -+ NET_IPV4_IP_MASQ_DEBUG=50, -+ NET_TCP_SYNCOOKIES=51, -+ NET_TCP_STDURG=52, -+ NET_TCP_RFC1337=53, -+ NET_TCP_SYN_TAILDROP=54, -+ NET_TCP_MAX_SYN_BACKLOG=55, -+ NET_IPV4_LOCAL_PORT_RANGE=56, -+ NET_IPV4_ICMP_ECHO_IGNORE_ALL=57, -+ NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS=58, -+ NET_IPV4_ICMP_SOURCEQUENCH_RATE=59, -+ NET_IPV4_ICMP_DESTUNREACH_RATE=60, -+ NET_IPV4_ICMP_TIMEEXCEED_RATE=61, -+ NET_IPV4_ICMP_PARAMPROB_RATE=62, -+ NET_IPV4_ICMP_ECHOREPLY_RATE=63, -+ NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=64, -+ NET_IPV4_IGMP_MAX_MEMBERSHIPS=65, -+ NET_TCP_TW_RECYCLE=66, -+ NET_IPV4_ALWAYS_DEFRAG=67, -+ NET_IPV4_TCP_KEEPALIVE_INTVL=68, -+ NET_IPV4_INET_PEER_THRESHOLD=69, -+ NET_IPV4_INET_PEER_MINTTL=70, -+ NET_IPV4_INET_PEER_MAXTTL=71, -+ NET_IPV4_INET_PEER_GC_MINTIME=72, -+ NET_IPV4_INET_PEER_GC_MAXTIME=73, -+ NET_TCP_ORPHAN_RETRIES=74, -+ NET_TCP_ABORT_ON_OVERFLOW=75, -+ NET_TCP_SYNACK_RETRIES=76, -+ NET_TCP_MAX_ORPHANS=77, -+ NET_TCP_MAX_TW_BUCKETS=78, -+ NET_TCP_FACK=79, -+ NET_TCP_REORDERING=80, -+ NET_TCP_ECN=81, -+ NET_TCP_DSACK=82, -+ NET_TCP_MEM=83, -+ NET_TCP_WMEM=84, -+ NET_TCP_RMEM=85, -+ NET_TCP_APP_WIN=86, -+ NET_TCP_ADV_WIN_SCALE=87, -+ NET_IPV4_NONLOCAL_BIND=88, -+ NET_IPV4_ICMP_RATELIMIT=89, -+ NET_IPV4_ICMP_RATEMASK=90, -+ NET_TCP_TW_REUSE=91, -+ NET_TCP_FRTO=92, -+ NET_TCP_LOW_LATENCY=93, -+ NET_IPV4_IPFRAG_SECRET_INTERVAL=94, -+ NET_TCP_WESTWOOD=95, -+ NET_IPV4_IGMP_MAX_MSF=96, -+ NET_TCP_NO_METRICS_SAVE=97, -+ NET_TCP_VEGAS=98, -+ NET_TCP_VEGAS_ALPHA=99, -+ NET_TCP_VEGAS_BETA=100, -+ NET_TCP_VEGAS_GAMMA=101, -+ NET_TCP_BIC=102, -+ NET_TCP_BIC_FAST_CONVERGENCE=103, -+ NET_TCP_BIC_LOW_WINDOW=104, -+ NET_TCP_DEFAULT_WIN_SCALE=105, -+ NET_TCP_MODERATE_RCVBUF=106, -+}; -+ -+enum { -+ NET_IPV4_ROUTE_FLUSH=1, -+ NET_IPV4_ROUTE_MIN_DELAY=2, -+ NET_IPV4_ROUTE_MAX_DELAY=3, -+ NET_IPV4_ROUTE_GC_THRESH=4, -+ NET_IPV4_ROUTE_MAX_SIZE=5, -+ NET_IPV4_ROUTE_GC_MIN_INTERVAL=6, -+ NET_IPV4_ROUTE_GC_TIMEOUT=7, -+ NET_IPV4_ROUTE_GC_INTERVAL=8, -+ NET_IPV4_ROUTE_REDIRECT_LOAD=9, -+ NET_IPV4_ROUTE_REDIRECT_NUMBER=10, -+ NET_IPV4_ROUTE_REDIRECT_SILENCE=11, -+ NET_IPV4_ROUTE_ERROR_COST=12, -+ NET_IPV4_ROUTE_ERROR_BURST=13, -+ NET_IPV4_ROUTE_GC_ELASTICITY=14, -+ NET_IPV4_ROUTE_MTU_EXPIRES=15, -+ NET_IPV4_ROUTE_MIN_PMTU=16, -+ NET_IPV4_ROUTE_MIN_ADVMSS=17, -+ NET_IPV4_ROUTE_SECRET_INTERVAL=18, -+}; -+ -+enum -+{ -+ NET_PROTO_CONF_ALL=-2, -+ NET_PROTO_CONF_DEFAULT=-3 -+ -+ /* And device ifindices ... */ -+}; -+ -+enum -+{ -+ NET_IPV4_CONF_FORWARDING=1, -+ NET_IPV4_CONF_MC_FORWARDING=2, -+ NET_IPV4_CONF_PROXY_ARP=3, -+ NET_IPV4_CONF_ACCEPT_REDIRECTS=4, -+ NET_IPV4_CONF_SECURE_REDIRECTS=5, -+ NET_IPV4_CONF_SEND_REDIRECTS=6, -+ NET_IPV4_CONF_SHARED_MEDIA=7, -+ NET_IPV4_CONF_RP_FILTER=8, -+ NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9, -+ NET_IPV4_CONF_BOOTP_RELAY=10, -+ NET_IPV4_CONF_LOG_MARTIANS=11, -+ NET_IPV4_CONF_TAG=12, -+ NET_IPV4_CONF_ARPFILTER=13, -+ NET_IPV4_CONF_MEDIUM_ID=14, -+ NET_IPV4_CONF_FORCE_IGMP_VERSION=17, -+ NET_IPV4_CONF_ARP_ANNOUNCE=18, -+ NET_IPV4_CONF_ARP_IGNORE=19, -+}; -+ -+/* /proc/sys/net/ipv4/netfilter */ -+enum -+{ -+ NET_IPV4_NF_CONNTRACK_MAX=1, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT=2, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV=3, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED=4, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT=5, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT=6, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK=7, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT=8, -+ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE=9, -+ NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT=10, -+ NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11, -+ NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12, -+ NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13, -+ NET_IPV4_NF_CONNTRACK_BUCKETS=14, -+}; -+ -+/* /proc/sys/net/ipv6 */ -+enum { -+ NET_IPV6_CONF=16, -+ NET_IPV6_NEIGH=17, -+ NET_IPV6_ROUTE=18, -+ NET_IPV6_ICMP=19, -+ NET_IPV6_BINDV6ONLY=20, -+ NET_IPV6_MLD_MAX_MSF=25, -+}; -+ -+enum { -+ NET_IPV6_ROUTE_FLUSH=1, -+ NET_IPV6_ROUTE_GC_THRESH=2, -+ NET_IPV6_ROUTE_MAX_SIZE=3, -+ NET_IPV6_ROUTE_GC_MIN_INTERVAL=4, -+ NET_IPV6_ROUTE_GC_TIMEOUT=5, -+ NET_IPV6_ROUTE_GC_INTERVAL=6, -+ NET_IPV6_ROUTE_GC_ELASTICITY=7, -+ NET_IPV6_ROUTE_MTU_EXPIRES=8, -+ NET_IPV6_ROUTE_MIN_ADVMSS=9 -+}; -+ -+enum { -+ NET_IPV6_FORWARDING=1, -+ NET_IPV6_HOP_LIMIT=2, -+ NET_IPV6_MTU=3, -+ NET_IPV6_ACCEPT_RA=4, -+ NET_IPV6_ACCEPT_REDIRECTS=5, -+ NET_IPV6_AUTOCONF=6, -+ NET_IPV6_DAD_TRANSMITS=7, -+ NET_IPV6_RTR_SOLICITS=8, -+ NET_IPV6_RTR_SOLICIT_INTERVAL=9, -+ NET_IPV6_RTR_SOLICIT_DELAY=10 -+}; -+ -+/* /proc/sys/net/ipv6/icmp */ -+enum { -+ NET_IPV6_ICMP_RATELIMIT=1 -+}; -+ -+/* /proc/sys/net/<protocol>/neigh/<dev> */ -+enum { -+ NET_NEIGH_MCAST_SOLICIT=1, -+ NET_NEIGH_UCAST_SOLICIT=2, -+ NET_NEIGH_APP_SOLICIT=3, -+ NET_NEIGH_RETRANS_TIME=4, -+ NET_NEIGH_REACHABLE_TIME=5, -+ NET_NEIGH_DELAY_PROBE_TIME=6, -+ NET_NEIGH_GC_STALE_TIME=7, -+ NET_NEIGH_UNRES_QLEN=8, -+ NET_NEIGH_PROXY_QLEN=9, -+ NET_NEIGH_ANYCAST_DELAY=10, -+ NET_NEIGH_PROXY_DELAY=11, -+ NET_NEIGH_LOCKTIME=12, -+ NET_NEIGH_GC_INTERVAL=13, -+ NET_NEIGH_GC_THRESH1=14, -+ NET_NEIGH_GC_THRESH2=15, -+ NET_NEIGH_GC_THRESH3=16 -+}; -+ -+/* /proc/sys/net/ipx */ -+enum { -+ NET_IPX_PPROP_BROADCASTING=1, -+ NET_IPX_FORWARDING=2 -+}; -+ -+ -+/* /proc/sys/net/appletalk */ -+enum { -+ NET_ATALK_AARP_EXPIRY_TIME=1, -+ NET_ATALK_AARP_TICK_TIME=2, -+ NET_ATALK_AARP_RETRANSMIT_LIMIT=3, -+ NET_ATALK_AARP_RESOLVE_TIME=4 -+}; -+ -+ -+/* /proc/sys/net/netrom */ -+enum { -+ NET_NETROM_DEFAULT_PATH_QUALITY=1, -+ NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER=2, -+ NET_NETROM_NETWORK_TTL_INITIALISER=3, -+ NET_NETROM_TRANSPORT_TIMEOUT=4, -+ NET_NETROM_TRANSPORT_MAXIMUM_TRIES=5, -+ NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY=6, -+ NET_NETROM_TRANSPORT_BUSY_DELAY=7, -+ NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8, -+ NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9, -+ NET_NETROM_ROUTING_CONTROL=10, -+ NET_NETROM_LINK_FAILS_COUNT=11 -+}; -+ -+/* /proc/sys/net/ax25 */ -+enum { -+ NET_AX25_IP_DEFAULT_MODE=1, -+ NET_AX25_DEFAULT_MODE=2, -+ NET_AX25_BACKOFF_TYPE=3, -+ NET_AX25_CONNECT_MODE=4, -+ NET_AX25_STANDARD_WINDOW=5, -+ NET_AX25_EXTENDED_WINDOW=6, -+ NET_AX25_T1_TIMEOUT=7, -+ NET_AX25_T2_TIMEOUT=8, -+ NET_AX25_T3_TIMEOUT=9, -+ NET_AX25_IDLE_TIMEOUT=10, -+ NET_AX25_N2=11, -+ NET_AX25_PACLEN=12, -+ NET_AX25_PROTOCOL=13, -+ NET_AX25_DAMA_SLAVE_TIMEOUT=14 -+}; -+ -+/* /proc/sys/net/rose */ -+enum { -+ NET_ROSE_RESTART_REQUEST_TIMEOUT=1, -+ NET_ROSE_CALL_REQUEST_TIMEOUT=2, -+ NET_ROSE_RESET_REQUEST_TIMEOUT=3, -+ NET_ROSE_CLEAR_REQUEST_TIMEOUT=4, -+ NET_ROSE_ACK_HOLD_BACK_TIMEOUT=5, -+ NET_ROSE_ROUTING_CONTROL=6, -+ NET_ROSE_LINK_FAIL_TIMEOUT=7, -+ NET_ROSE_MAX_VCS=8, -+ NET_ROSE_WINDOW_SIZE=9, -+ NET_ROSE_NO_ACTIVITY_TIMEOUT=10 -+}; -+ -+/* /proc/sys/net/x25 */ -+enum { -+ NET_X25_RESTART_REQUEST_TIMEOUT=1, -+ NET_X25_CALL_REQUEST_TIMEOUT=2, -+ NET_X25_RESET_REQUEST_TIMEOUT=3, -+ NET_X25_CLEAR_REQUEST_TIMEOUT=4, -+ NET_X25_ACK_HOLD_BACK_TIMEOUT=5 -+}; -+ -+/* /proc/sys/net/token-ring */ -+enum -+{ -+ NET_TR_RIF_TIMEOUT=1 -+}; -+ -+/* /proc/sys/net/decnet/ */ -+enum { -+ NET_DECNET_NODE_TYPE = 1, -+ NET_DECNET_NODE_ADDRESS = 2, -+ NET_DECNET_NODE_NAME = 3, -+ NET_DECNET_DEFAULT_DEVICE = 4, -+ NET_DECNET_TIME_WAIT = 5, -+ NET_DECNET_DN_COUNT = 6, -+ NET_DECNET_DI_COUNT = 7, -+ NET_DECNET_DR_COUNT = 8, -+ NET_DECNET_DST_GC_INTERVAL = 9, -+ NET_DECNET_CONF = 10, -+ NET_DECNET_NO_FC_MAX_CWND = 11, -+ NET_DECNET_DEBUG_LEVEL = 255 -+}; -+ -+/* /proc/sys/net/sctp */ -+enum { -+ NET_SCTP_RTO_INITIAL = 1, -+ NET_SCTP_RTO_MIN = 2, -+ NET_SCTP_RTO_MAX = 3, -+ NET_SCTP_RTO_ALPHA = 4, -+ NET_SCTP_RTO_BETA = 5, -+ NET_SCTP_VALID_COOKIE_LIFE = 6, -+ NET_SCTP_ASSOCIATION_MAX_RETRANS = 7, -+ NET_SCTP_PATH_MAX_RETRANS = 8, -+ NET_SCTP_MAX_INIT_RETRANSMITS = 9, -+ NET_SCTP_HB_INTERVAL = 10, -+ NET_SCTP_PRESERVE_ENABLE = 11, -+ NET_SCTP_MAX_BURST = 12, -+ NET_SCTP_ADDIP_ENABLE = 13, -+ NET_SCTP_PRSCTP_ENABLE = 14, -+}; -+/* /proc/sys/net/khttpd/ */ -+enum { -+ NET_KHTTPD_DOCROOT = 1, -+ NET_KHTTPD_START = 2, -+ NET_KHTTPD_STOP = 3, -+ NET_KHTTPD_UNLOAD = 4, -+ NET_KHTTPD_CLIENTPORT = 5, -+ NET_KHTTPD_PERMREQ = 6, -+ NET_KHTTPD_PERMFORBID = 7, -+ NET_KHTTPD_LOGGING = 8, -+ NET_KHTTPD_SERVERPORT = 9, -+ NET_KHTTPD_DYNAMICSTRING= 10, -+ NET_KHTTPD_SLOPPYMIME = 11, -+ NET_KHTTPD_THREADS = 12, -+ NET_KHTTPD_MAXCONNECT = 13 -+}; -+ -+/* /proc/sys/net/decnet/conf/<dev> */ -+enum { -+ NET_DECNET_CONF_LOOPBACK = -2, -+ NET_DECNET_CONF_DDCMP = -3, -+ NET_DECNET_CONF_PPP = -4, -+ NET_DECNET_CONF_X25 = -5, -+ NET_DECNET_CONF_GRE = -6, -+ NET_DECNET_CONF_ETHER = -7 -+ -+ /* ... and ifindex of devices */ -+}; -+ -+/* /proc/sys/net/decnet/conf/<dev>/ */ -+enum { -+ NET_DECNET_CONF_DEV_PRIORITY = 1, -+ NET_DECNET_CONF_DEV_T1 = 2, -+ NET_DECNET_CONF_DEV_T2 = 3, -+ NET_DECNET_CONF_DEV_T3 = 4, -+ NET_DECNET_CONF_DEV_FORWARDING = 5, -+ NET_DECNET_CONF_DEV_BLKSIZE = 6, -+ NET_DECNET_CONF_DEV_STATE = 7 -+}; -+ -+/* CTL_PROC names: */ -+ -+/* CTL_FS names: */ -+enum -+{ -+ FS_NRINODE=1, /* int:current number of allocated inodes */ -+ FS_STATINODE=2, -+ FS_MAXINODE=3, /* int:maximum number of inodes that can be allocated */ -+ FS_NRDQUOT=4, /* int:current number of allocated dquots */ -+ /* was FS_MAXDQUOT */ -+ FS_NRFILE=6, /* int:current number of allocated filedescriptors */ -+ FS_MAXFILE=7, /* int:maximum number of filedescriptors that can be allocated */ -+ FS_DENTRY=8, -+ FS_NRSUPER=9, /* int:current number of allocated super_blocks */ -+ FS_MAXSUPER=10, /* int:maximum number of super_blocks that can be allocated */ -+ FS_OVERFLOWUID=11, /* int: overflow UID */ -+ FS_OVERFLOWGID=12, /* int: overflow GID */ -+ FS_LEASES=13, /* int: leases enabled */ -+ FS_DIR_NOTIFY=14, /* int: directory notification enabled */ -+ FS_LEASE_TIME=15, /* int: maximum time to wait for a lease break */ -+ FS_DQSTATS=16, /* dir: disc quota usage statistics and settings */ -+ FS_XFS=17, /* struct: control xfs parameters */ -+}; -+ -+/* /proc/sys/fs/quota/ */ -+enum { -+ FS_DQ_LOOKUPS = 1, -+ FS_DQ_DROPS = 2, -+ FS_DQ_READS = 3, -+ FS_DQ_WRITES = 4, -+ FS_DQ_CACHE_HITS = 5, -+ FS_DQ_ALLOCATED = 6, -+ FS_DQ_FREE = 7, -+ FS_DQ_SYNCS = 8, -+ FS_DQ_WARNINGS = 9, -+}; -+ -+/* CTL_DEBUG names: */ -+ -+/* CTL_DEV names: */ -+enum { -+ DEV_CDROM=1, -+ DEV_HWMON=2, -+ DEV_PARPORT=3, -+ DEV_RAID=4, -+ DEV_MAC_HID=5 -+}; -+ -+/* /proc/sys/dev/cdrom */ -+enum { -+ DEV_CDROM_INFO=1, -+ DEV_CDROM_AUTOCLOSE=2, -+ DEV_CDROM_AUTOEJECT=3, -+ DEV_CDROM_DEBUG=4, -+ DEV_CDROM_LOCK=5, -+ DEV_CDROM_CHECK_MEDIA=6 -+}; -+ -+/* /proc/sys/dev/parport */ -+enum { -+ DEV_PARPORT_DEFAULT=-3 -+}; -+ -+/* /proc/sys/dev/raid */ -+enum { -+ DEV_RAID_SPEED_LIMIT_MIN=1, -+ DEV_RAID_SPEED_LIMIT_MAX=2 -+}; -+ -+/* /proc/sys/dev/parport/default */ -+enum { -+ DEV_PARPORT_DEFAULT_TIMESLICE=1, -+ DEV_PARPORT_DEFAULT_SPINTIME=2 -+}; -+ -+/* /proc/sys/dev/parport/parport n */ -+enum { -+ DEV_PARPORT_SPINTIME=1, -+ DEV_PARPORT_BASE_ADDR=2, -+ DEV_PARPORT_IRQ=3, -+ DEV_PARPORT_DMA=4, -+ DEV_PARPORT_MODES=5, -+ DEV_PARPORT_DEVICES=6, -+ DEV_PARPORT_AUTOPROBE=16 -+}; -+ -+/* /proc/sys/dev/parport/parport n/devices/ */ -+enum { -+ DEV_PARPORT_DEVICES_ACTIVE=-3, -+}; -+ -+/* /proc/sys/dev/parport/parport n/devices/device n */ -+enum { -+ DEV_PARPORT_DEVICE_TIMESLICE=1, -+}; -+ -+/* /proc/sys/dev/mac_hid */ -+enum { -+ DEV_MAC_HID_KEYBOARD_SENDS_LINUX_KEYCODES=1, -+ DEV_MAC_HID_KEYBOARD_LOCK_KEYCODES=2, -+ DEV_MAC_HID_MOUSE_BUTTON_EMULATION=3, -+ DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE=4, -+ DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE=5, -+ DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES=6 -+}; -+ -+/* /proc/sys/abi */ -+enum -+{ -+ ABI_DEFHANDLER_COFF=1, /* default handler for coff binaries */ -+ ABI_DEFHANDLER_ELF=2, /* default handler for ELF binaries */ -+ ABI_DEFHANDLER_LCALL7=3,/* default handler for procs using lcall7 */ -+ ABI_DEFHANDLER_LIBCSO=4,/* default handler for an libc.so ELF interp */ -+ ABI_TRACE=5, /* tracing flags */ -+ ABI_FAKE_UTSNAME=6, /* fake target utsname information */ -+}; -+ -+#ifdef __KERNEL__ -+ -+extern asmlinkage long sys_sysctl(struct __sysctl_args *); -+extern void sysctl_init(void); -+ -+typedef struct ctl_table ctl_table; -+ -+typedef int ctl_handler (ctl_table *table, int *name, int nlen, -+ void *oldval, size_t *oldlenp, -+ void *newval, size_t newlen, -+ void **context); -+ -+typedef int proc_handler (ctl_table *ctl, int write, struct file * filp, -+ void *buffer, size_t *lenp); -+ -+extern int proc_dostring(ctl_table *, int, struct file *, -+ void *, size_t *); -+extern int proc_dointvec(ctl_table *, int, struct file *, -+ void *, size_t *); -+extern int proc_dointvec_bset(ctl_table *, int, struct file *, -+ void *, size_t *); -+extern int proc_dointvec_minmax(ctl_table *, int, struct file *, -+ void *, size_t *); -+extern int proc_dointvec_jiffies(ctl_table *, int, struct file *, -+ void *, size_t *); -+extern int proc_doulongvec_minmax(ctl_table *, int, struct file *, -+ void *, size_t *); -+extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int, -+ struct file *, void *, size_t *); -+ -+extern int do_sysctl (int *name, int nlen, -+ void *oldval, size_t *oldlenp, -+ void *newval, size_t newlen); -+ -+extern int do_sysctl_strategy (ctl_table *table, -+ int *name, int nlen, -+ void *oldval, size_t *oldlenp, -+ void *newval, size_t newlen, void ** context); -+ -+extern ctl_handler sysctl_string; -+extern ctl_handler sysctl_intvec; -+extern ctl_handler sysctl_jiffies; -+ -+ -+/* -+ * Register a set of sysctl names by calling register_sysctl_table -+ * with an initialised array of ctl_table's. An entry with zero -+ * ctl_name terminates the table. table->de will be set up by the -+ * registration and need not be initialised in advance. -+ * -+ * sysctl names can be mirrored automatically under /proc/sys. The -+ * procname supplied controls /proc naming. -+ * -+ * The table's mode will be honoured both for sys_sysctl(2) and -+ * proc-fs access. -+ * -+ * Leaf nodes in the sysctl tree will be represented by a single file -+ * under /proc; non-leaf nodes will be represented by directories. A -+ * null procname disables /proc mirroring at this node. -+ * -+ * sysctl(2) can automatically manage read and write requests through -+ * the sysctl table. The data and maxlen fields of the ctl_table -+ * struct enable minimal validation of the values being written to be -+ * performed, and the mode field allows minimal authentication. -+ * -+ * More sophisticated management can be enabled by the provision of a -+ * strategy routine with the table entry. This will be called before -+ * any automatic read or write of the data is performed. -+ * -+ * The strategy routine may return: -+ * <0: Error occurred (error is passed to user process) -+ * 0: OK - proceed with automatic read or write. -+ * >0: OK - read or write has been done by the strategy routine, so -+ * return immediately. -+ * -+ * There must be a proc_handler routine for any terminal nodes -+ * mirrored under /proc/sys (non-terminals are handled by a built-in -+ * directory handler). Several default handlers are available to -+ * cover common cases. -+ */ -+ -+/* A sysctl table is an array of struct ctl_table: */ -+struct ctl_table -+{ -+ int ctl_name; /* Binary ID */ -+ const char *procname; /* Text ID for /proc/sys, or zero */ -+ void *data; -+ int maxlen; -+ mode_t mode; -+ ctl_table *child; -+ proc_handler *proc_handler; /* Callback for text formatting */ -+ ctl_handler *strategy; /* Callback function for all r/w */ -+ struct proc_dir_entry *de; /* /proc control block */ -+ void *extra1; -+ void *extra2; -+}; -+ -+/* struct ctl_table_header is used to maintain dynamic lists of -+ ctl_table trees. */ -+struct ctl_table_header -+{ -+ ctl_table *ctl_table; -+ struct list_head ctl_entry; -+}; -+ -+struct ctl_table_header * register_sysctl_table(ctl_table * table, -+ int insert_at_head); -+void unregister_sysctl_table(struct ctl_table_header * table); -+ -+#else /* __KERNEL__ */ -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _LINUX_SYSCTL_H */ -diff -Nur linux-mips-cvs/net/8021q/vlan_dev.c linux-ebtables/net/8021q/vlan_dev.c ---- linux-mips-cvs/net/8021q/vlan_dev.c 2004-11-29 18:47:19.000000000 +0100 -+++ linux-ebtables/net/8021q/vlan_dev.c 2005-02-07 05:52:50.000000000 +0100 -@@ -488,6 +488,10 @@ - stats->tx_packets++; /* for statics only */ - stats->tx_bytes += skb->len; + /* TCP matching stuff */ + struct ip6t_tcp +--- linux-2.4.29/include/linux/netfilter_arp/arp_tables.h 2003-08-25 13:44:44.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_arp/arp_tables.h 2005-03-14 21:24:31.000000000 +0100 +@@ -154,7 +154,7 @@ struct arpt_entry + #define ARPT_CONTINUE 0xFFFFFFFF -+ skb->protocol = __constant_htons(ETH_P_8021Q); -+ skb->mac.raw -= VLAN_HLEN; -+ skb->nh.raw -= VLAN_HLEN; -+ - skb->dev = VLAN_DEV_INFO(dev)->real_dev; - dev_queue_xmit(skb); + /* For standard target */ +-#define ARPT_RETURN (-NF_MAX_VERDICT - 1) ++#define ARPT_RETURN (-NF_REPEAT - 1) -diff -Nur linux-mips-cvs/net/Config.in linux-ebtables/net/Config.in ---- linux-mips-cvs/net/Config.in 2005-01-09 20:34:04.000000000 +0100 -+++ linux-ebtables/net/Config.in 2005-02-07 05:52:50.000000000 +0100 -@@ -70,6 +70,9 @@ - source net/decnet/Config.in - fi - dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET -+if [ "$CONFIG_BRIDGE" != "n" -a "$CONFIG_NETFILTER" != "n" ]; then -+ source net/bridge/netfilter/Config.in -+fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 - tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB -diff -Nur linux-mips-cvs/net/Config.in.orig linux-ebtables/net/Config.in.orig ---- linux-mips-cvs/net/Config.in.orig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/Config.in.orig 2005-01-09 20:34:04.000000000 +0100 -@@ -0,0 +1,107 @@ -+# -+# Network configuration -+# -+mainmenu_option next_comment -+comment 'Networking options' -+tristate 'Packet socket' CONFIG_PACKET -+if [ "$CONFIG_PACKET" != "n" ]; then -+ bool ' Packet socket: mmapped IO' CONFIG_PACKET_MMAP -+fi -+ -+tristate 'Netlink device emulation' CONFIG_NETLINK_DEV -+ -+bool 'Network packet filtering (replaces ipchains)' CONFIG_NETFILTER -+if [ "$CONFIG_NETFILTER" = "y" ]; then -+ bool ' Network packet filtering debugging' CONFIG_NETFILTER_DEBUG -+fi -+bool 'Socket Filtering' CONFIG_FILTER -+tristate 'Unix domain sockets' CONFIG_UNIX -+bool 'TCP/IP networking' CONFIG_INET -+if [ "$CONFIG_INET" = "y" ]; then -+ source net/ipv4/Config.in -+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+# IPv6 as module will cause a CRASH if you try to unload it -+ tristate ' The IPv6 protocol (EXPERIMENTAL)' CONFIG_IPV6 -+ if [ "$CONFIG_IPV6" != "n" ]; then -+ source net/ipv6/Config.in -+ fi -+ fi -+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ source net/khttpd/Config.in -+ fi -+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ source net/sctp/Config.in -+ fi -+fi -+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ tristate 'Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)' CONFIG_ATM -+ if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then -+ if [ "$CONFIG_INET" = "y" ]; then -+ dep_tristate ' Classical IP over ATM' CONFIG_ATM_CLIP $CONFIG_ATM -+ if [ "$CONFIG_ATM_CLIP" != "n" ]; then -+ bool ' Do NOT send ICMP if no neighbour' CONFIG_ATM_CLIP_NO_ICMP -+ fi -+ fi -+ dep_tristate ' LAN Emulation (LANE) support' CONFIG_ATM_LANE $CONFIG_ATM -+ if [ "$CONFIG_INET" = "y" -a "$CONFIG_ATM_LANE" != "n" ]; then -+ tristate ' Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA -+ fi -+ dep_tristate ' RFC1483/2684 Bridged protocols' CONFIG_ATM_BR2684 $CONFIG_ATM -+ if [ "$CONFIG_ATM_BR2684" != "n" ]; then -+ bool ' Per-VC IP filter kludge' CONFIG_ATM_BR2684_IPFILTER -+ fi -+ fi -+fi -+tristate '802.1Q VLAN Support' CONFIG_VLAN_8021Q -+ -+comment ' ' -+tristate 'The IPX protocol' CONFIG_IPX -+if [ "$CONFIG_IPX" != "n" ]; then -+ source net/ipx/Config.in -+fi -+ -+tristate 'Appletalk protocol support' CONFIG_ATALK -+if [ "$CONFIG_ATALK" != "n" ]; then -+ source drivers/net/appletalk/Config.in -+fi -+ -+tristate 'DECnet Support' CONFIG_DECNET -+if [ "$CONFIG_DECNET" != "n" ]; then -+ source net/decnet/Config.in -+fi -+dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET -+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 -+ tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB -+ bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC -+ bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT -+# if [ "$CONFIG_LLC" = "y" ]; then -+# bool ' Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI -+# fi -+ if [ "$CONFIG_INET" = "y" ]; then -+ tristate 'Acorn Econet/AUN protocols (EXPERIMENTAL)' CONFIG_ECONET -+ if [ "$CONFIG_ECONET" != "n" ]; then -+ bool ' AUN over UDP' CONFIG_ECONET_AUNUDP -+ bool ' Native Econet' CONFIG_ECONET_NATIVE -+ fi -+ fi -+ tristate 'WAN router' CONFIG_WAN_ROUTER -+ bool 'Fast switching (read help!)' CONFIG_NET_FASTROUTE -+ bool 'Forwarding between high speed interfaces' CONFIG_NET_HW_FLOWCONTROL -+fi -+ -+mainmenu_option next_comment -+comment 'QoS and/or fair queueing' -+bool 'QoS and/or fair queueing' CONFIG_NET_SCHED -+if [ "$CONFIG_NET_SCHED" = "y" ]; then -+ source net/sched/Config.in -+fi -+#bool 'Network code profiler' CONFIG_NET_PROFILE -+endmenu -+ -+mainmenu_option next_comment -+comment 'Network testing' -+dep_tristate 'Packet Generator (USE WITH CAUTION)' CONFIG_NET_PKTGEN $CONFIG_PROC_FS -+endmenu -+ -+endmenu -diff -Nur linux-mips-cvs/net/Makefile linux-ebtables/net/Makefile ---- linux-mips-cvs/net/Makefile 2004-08-14 20:39:04.000000000 +0200 -+++ linux-ebtables/net/Makefile 2005-02-07 05:52:50.000000000 +0100 + /* The argument to ARPT_SO_GET_INFO */ + struct arpt_getinfo +--- linux-2.4.29/net/Makefile 2004-08-08 01:26:06.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/net/Makefile 2005-03-14 00:00:29.000000000 +0100 @@ -7,7 +7,8 @@ O_TARGET := network.o @@ -2096,7 +392,7 @@ diff -Nur linux-mips-cvs/net/Makefile linux-ebtables/net/Makefile export-objs := netsyms.o subdir-y := core ethernet -@@ -27,6 +28,12 @@ +@@ -27,6 +28,12 @@ subdir-$(CONFIG_NETFILTER) += ipv6/netfi endif endif @@ -2109,1477 +405,357 @@ diff -Nur linux-mips-cvs/net/Makefile linux-ebtables/net/Makefile subdir-$(CONFIG_KHTTPD) += khttpd subdir-$(CONFIG_PACKET) += packet subdir-$(CONFIG_NET_SCHED) += sched -diff -Nur linux-mips-cvs/net/bridge/Makefile linux-ebtables/net/bridge/Makefile ---- linux-mips-cvs/net/bridge/Makefile 2001-01-10 18:18:10.000000000 +0100 -+++ linux-ebtables/net/bridge/Makefile 2005-02-07 05:52:50.000000000 +0100 -@@ -7,10 +7,17 @@ - # - # Note 2! The CFLAGS definition is now in the main makefile... - -+export-objs := br.o -+ - O_TARGET := bridge.o - obj-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \ - br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \ - br_stp_if.o br_stp_timer.o -+ -+ifeq ($(CONFIG_NETFILTER),y) -+obj-y += br_netfilter.o -+endif -+ - obj-m := $(O_TARGET) - - include $(TOPDIR)/Rules.make -diff -Nur linux-mips-cvs/net/bridge/br.c linux-ebtables/net/bridge/br.c ---- linux-mips-cvs/net/bridge/br.c 2004-08-14 20:39:04.000000000 +0200 -+++ linux-ebtables/net/bridge/br.c 2005-02-07 05:52:50.000000000 +0100 -@@ -30,6 +30,8 @@ - #include "../atm/lec.h" - #endif - -+int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; +--- linux-2.4.29/net/Config.in 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/Config.in 2005-03-14 00:00:29.000000000 +0100 +@@ -70,6 +70,9 @@ if [ "$CONFIG_DECNET" != "n" ]; then + source net/decnet/Config.in + fi + dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET ++if [ "$CONFIG_BRIDGE" != "n" -a "$CONFIG_NETFILTER" != "n" ]; then ++ source net/bridge/netfilter/Config.in ++fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 + tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/Makefile 2005-03-14 00:00:29.000000000 +0100 +@@ -0,0 +1,34 @@ ++# ++# Makefile for the netfilter modules on top of bridging. ++# ++# Note! Dependencies are done automagically by 'make dep', which also ++# removes any old dependencies. DON'T put your own dependencies here ++# unless it's something special (ie not a .c file). ++# ++# Note 2! The CFLAGS definition is now in the main makefile... + - void br_dec_use_count() - { - MOD_DEC_USE_COUNT; -@@ -44,6 +46,10 @@ - { - printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); - -+#ifdef CONFIG_NETFILTER -+ if (br_netfilter_init()) -+ return 1; -+#endif - br_handle_frame_hook = br_handle_frame; - br_ioctl_hook = br_ioctl_deviceless_stub; - #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) -@@ -57,6 +63,9 @@ - - static void __exit br_deinit(void) - { -+#ifdef CONFIG_NETFILTER -+ br_netfilter_fini(); -+#endif - unregister_netdevice_notifier(&br_device_notifier); - - rtnl_lock(); -@@ -73,7 +82,7 @@ - #endif - } - --EXPORT_NO_SYMBOLS; -+EXPORT_SYMBOL(br_should_route_hook); - - module_init(br_init) - module_exit(br_deinit) -diff -Nur linux-mips-cvs/net/bridge/br_forward.c linux-ebtables/net/bridge/br_forward.c ---- linux-mips-cvs/net/bridge/br_forward.c 2003-11-17 02:07:47.000000000 +0100 -+++ linux-ebtables/net/bridge/br_forward.c 2005-02-07 05:52:50.000000000 +0100 -@@ -30,18 +30,21 @@ - return 1; - } - --static int __dev_queue_push_xmit(struct sk_buff *skb) -+int br_dev_queue_push_xmit(struct sk_buff *skb) - { -+#ifdef CONFIG_NETFILTER -+ nf_bridge_maybe_copy_header(skb); -+#endif - skb_push(skb, ETH_HLEN); - dev_queue_xmit(skb); - - return 0; - } - --static int __br_forward_finish(struct sk_buff *skb) -+int br_forward_finish(struct sk_buff *skb) - { - NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev, -- __dev_queue_push_xmit); -+ br_dev_queue_push_xmit); - - return 0; - } -@@ -49,8 +52,11 @@ - static void __br_deliver(struct net_bridge_port *to, struct sk_buff *skb) - { - skb->dev = to->dev; -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug = 0; -+#endif - NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, -- __br_forward_finish); -+ br_forward_finish); - } - - static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb) -@@ -62,7 +68,7 @@ - skb->ip_summed = CHECKSUM_NONE; - - NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, -- __br_forward_finish); -+ br_forward_finish); - } - - /* called under bridge lock */ -diff -Nur linux-mips-cvs/net/bridge/br_input.c linux-ebtables/net/bridge/br_input.c ---- linux-mips-cvs/net/bridge/br_input.c 2003-08-13 19:19:30.000000000 +0200 -+++ linux-ebtables/net/bridge/br_input.c 2005-02-07 05:52:50.000000000 +0100 -@@ -24,6 +24,9 @@ - - static int br_pass_frame_up_finish(struct sk_buff *skb) - { -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug = 0; -+#endif - netif_rx(skb); - - return 0; -@@ -46,7 +49,7 @@ - br_pass_frame_up_finish); - } - --static int br_handle_frame_finish(struct sk_buff *skb) -+int br_handle_frame_finish(struct sk_buff *skb) - { - struct net_bridge *br; - unsigned char *dest; -@@ -112,7 +115,7 @@ - return 0; - } - --void br_handle_frame(struct sk_buff *skb) -+int br_handle_frame(struct sk_buff *skb) - { - struct net_bridge *br; - unsigned char *dest; -@@ -146,26 +149,35 @@ - goto handle_special_frame; - - if (p->state == BR_STATE_FORWARDING) { -+ if (br_should_route_hook && br_should_route_hook(&skb)) { -+ read_unlock(&br->lock); -+ return -1; -+ } ++O_TARGET := netfilter.o + -+ if (!memcmp(p->br->dev.dev_addr, dest, ETH_ALEN)) -+ skb->pkt_type = PACKET_HOST; ++export-objs := ebtables.o + - NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, - br_handle_frame_finish); - read_unlock(&br->lock); -- return; -+ return 0; - } - - err: - read_unlock(&br->lock); - err_nolock: - kfree_skb(skb); -- return; -+ return 0; - - handle_special_frame: - if (!dest[5]) { - NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,NULL, - br_stp_handle_bpdu); - read_unlock(&br->lock); -- return; -+ return 0; - } - - read_unlock(&br->lock); - kfree_skb(skb); -+ return 0; - } -diff -Nur linux-mips-cvs/net/bridge/br_netfilter.c linux-ebtables/net/bridge/br_netfilter.c ---- linux-mips-cvs/net/bridge/br_netfilter.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/br_netfilter.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,1103 @@ ++obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o ++obj-$(CONFIG_BRIDGE_EBT_T_FILTER) += ebtable_filter.o ++obj-$(CONFIG_BRIDGE_EBT_T_NAT) += ebtable_nat.o ++obj-$(CONFIG_BRIDGE_EBT_BROUTE) += ebtable_broute.o ++obj-$(CONFIG_BRIDGE_EBT_802_3) += ebt_802_3.o ++obj-$(CONFIG_BRIDGE_EBT_ARPF) += ebt_arp.o ++obj-$(CONFIG_BRIDGE_EBT_AMONG) += ebt_among.o ++obj-$(CONFIG_BRIDGE_EBT_IPF) += ebt_ip.o ++obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o ++obj-$(CONFIG_BRIDGE_EBT_MARKF) += ebt_mark_m.o ++obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o ++obj-$(CONFIG_BRIDGE_EBT_STP) += ebt_stp.o ++obj-$(CONFIG_BRIDGE_EBT_VLANF) += ebt_vlan.o ++obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o ++obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_ulog.o ++obj-$(CONFIG_BRIDGE_EBT_ARPREPLY) += ebt_arpreply.o ++obj-$(CONFIG_BRIDGE_EBT_DNAT) += ebt_dnat.o ++obj-$(CONFIG_BRIDGE_EBT_MARK_T) += ebt_mark.o ++obj-$(CONFIG_BRIDGE_EBT_REDIRECT) += ebt_redirect.o ++obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o ++include $(TOPDIR)/Rules.make +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/Config.in 2005-03-14 00:00:29.000000000 +0100 +@@ -0,0 +1,23 @@ ++# ++# Bridge netfilter configuration ++# ++dep_tristate ' Bridge: ebtables' CONFIG_BRIDGE_NF_EBTABLES $CONFIG_BRIDGE ++dep_tristate ' ebt: filter table support' CONFIG_BRIDGE_EBT_T_FILTER $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: nat table support' CONFIG_BRIDGE_EBT_T_NAT $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: broute table support' CONFIG_BRIDGE_EBT_BROUTE $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: log support' CONFIG_BRIDGE_EBT_LOG $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: ulog support' CONFIG_BRIDGE_EBT_LOG $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: IP filter support' CONFIG_BRIDGE_EBT_IPF $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: ARP filter support' CONFIG_BRIDGE_EBT_ARPF $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: among filter support' CONFIG_BRIDGE_EBT_AMONG $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: limit filter support' CONFIG_BRIDGE_EBT_LIMIT $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: 802.1Q VLAN filter support' CONFIG_BRIDGE_EBT_VLANF $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: 802.3 filter support' CONFIG_BRIDGE_EBT_802_3 $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: packet type filter support' CONFIG_BRIDGE_EBT_PKTTYPE $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: STP filter support' CONFIG_BRIDGE_EBT_STP $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: mark filter support' CONFIG_BRIDGE_EBT_MARKF $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: arp reply target support' CONFIG_BRIDGE_EBT_ARPREPLY $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: snat target support' CONFIG_BRIDGE_EBT_SNAT $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: dnat target support' CONFIG_BRIDGE_EBT_DNAT $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: redirect target support' CONFIG_BRIDGE_EBT_REDIRECT $CONFIG_BRIDGE_NF_EBTABLES ++dep_tristate ' ebt: mark target support' CONFIG_BRIDGE_EBT_MARK_T $CONFIG_BRIDGE_NF_EBTABLES +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebtable_filter.c 2005-03-14 00:00:29.000000000 +0100 +@@ -0,0 +1,90 @@ +/* -+ * Handle firewalling -+ * Linux ethernet bridge ++ * ebtable_filter + * + * Authors: -+ * Lennert Buytenhek <buytenh@gnu.org> -+ * Bart De Schuymer (maintainer) <bdschuym@pandora.be> -+ * -+ * Changes: -+ * Apr 29 2003: physdev module support (bdschuym) -+ * Jun 19 2003: let arptables see bridged ARP traffic (bdschuym) -+ * Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge -+ * (bdschuym) -+ * Aug 28 2004: add IPv6 filtering (bdschuym) ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> + * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. ++ * April, 2002 + * -+ * Lennert dedicates this file to Kerstin Wurdinger. + */ + ++#include <linux/netfilter_bridge/ebtables.h> +#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/ip.h> -+#include <linux/netdevice.h> -+#include <linux/skbuff.h> -+#include <linux/if_ether.h> -+#include <linux/if_vlan.h> -+#include <linux/netfilter_bridge.h> -+#include <linux/netfilter_ipv4.h> -+#include <linux/netfilter_ipv6.h> -+#include <linux/in_route.h> -+#include <net/ip.h> -+#include <net/ipv6.h> -+#include <asm/uaccess.h> -+#include <asm/checksum.h> -+#include "br_private.h" -+#ifdef CONFIG_SYSCTL -+#include <linux/sysctl.h> -+#endif -+ -+#define skb_origaddr(skb) (((struct bridge_skb_cb *) \ -+ (skb->nf_bridge->data))->daddr.ipv4) -+#define store_orig_dstaddr(skb) (skb_origaddr(skb) = (skb)->nh.iph->daddr) -+#define dnat_took_place(skb) (skb_origaddr(skb) != (skb)->nh.iph->daddr) -+ -+#define has_bridge_parent(device) ((device)->br_port != NULL) -+#define bridge_parent(device) (&((device)->br_port->br->dev)) -+ -+#ifdef CONFIG_SYSCTL -+static struct ctl_table_header *brnf_sysctl_header; -+static int brnf_call_iptables = 1; -+static int brnf_call_ip6tables = 1; -+static int brnf_call_arptables = 1; -+static int brnf_filter_vlan_tagged = 1; -+#else -+#define brnf_filter_vlan_tagged 1 -+#endif -+ -+#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ -+ hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) && \ -+ brnf_filter_vlan_tagged) -+#define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) && \ -+ hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) && \ -+ brnf_filter_vlan_tagged) -+/* -+#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ -+ hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \ -+ brnf_filter_vlan_tagged) -+*/ + -+/* We need these fake structures to make netfilter happy -- -+ * lots of places assume that skb->dst != NULL, which isn't -+ * all that unreasonable. -+ * -+ * Currently, we fill in the PMTU entry because netfilter -+ * refragmentation needs it, and the rt_flags entry because -+ * ipt_REJECT needs it. Future netfilter modules might -+ * require us to fill additional fields. -+ */ -+static struct net_device __fake_net_device = { -+ .hard_header_len = ETH_HLEN -+}; -+ -+static struct rtable __fake_rtable = { -+ u: { -+ dst: { -+ __refcnt: ATOMIC_INIT(1), -+ dev: &__fake_net_device, -+ pmtu: 1500 -+ } -+ }, -+ -+ rt_flags: 0 -+}; -+ -+ -+/* PF_BRIDGE/PRE_ROUTING *********************************************/ -+/* Undo the changes made for ip6tables PREROUTING and continue the -+ * bridge PRE_ROUTING hook. */ -+static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) -+{ -+ struct nf_bridge_info *nf_bridge = skb->nf_bridge; -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING); -+#endif -+ -+ if (nf_bridge->mask & BRNF_PKT_TYPE) { -+ skb->pkt_type = PACKET_OTHERHOST; -+ nf_bridge->mask ^= BRNF_PKT_TYPE; -+ } -+ nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; -+ -+ skb->dst = (struct dst_entry *)&__fake_rtable; -+ dst_hold(skb->dst); -+ -+ skb->dev = nf_bridge->physindev; -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_push(skb, VLAN_HLEN); -+ skb->nh.raw -= VLAN_HLEN; -+ } -+ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, -+ br_handle_frame_finish, 1); -+ -+ return 0; -+} ++#define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \ ++ (1 << NF_BR_LOCAL_OUT)) + -+static void __br_dnat_complain(void) ++static struct ebt_entries initial_chains[] = +{ -+ static unsigned long last_complaint; -+ -+ if (jiffies - last_complaint >= 5 * HZ) { -+ printk(KERN_WARNING "Performing cross-bridge DNAT requires IP " -+ "forwarding to be enabled\n"); -+ last_complaint = jiffies; -+ } -+} -+ -+ -+/* This requires some explaining. If DNAT has taken place, -+ * we will need to fix up the destination Ethernet address, -+ * and this is a tricky process. -+ * -+ * There are two cases to consider: -+ * 1. The packet was DNAT'ed to a device in the same bridge -+ * port group as it was received on. We can still bridge -+ * the packet. -+ * 2. The packet was DNAT'ed to a different device, either -+ * a non-bridged device or another bridge port group. -+ * The packet will need to be routed. -+ * -+ * The correct way of distinguishing between these two cases is to -+ * call ip_route_input() and to look at skb->dst->dev, which is -+ * changed to the destination device if ip_route_input() succeeds. -+ * -+ * Let us first consider the case that ip_route_input() succeeds: -+ * -+ * If skb->dst->dev equals the logical bridge device the packet -+ * came in on, we can consider this bridging. We then call -+ * skb->dst->output() which will make the packet enter br_nf_local_out() -+ * not much later. In that function it is assured that the iptables -+ * FORWARD chain is traversed for the packet. -+ * -+ * Otherwise, the packet is considered to be routed and we just -+ * change the destination MAC address so that the packet will -+ * later be passed up to the IP stack to be routed. -+ * -+ * Let us now consider the case that ip_route_input() fails: -+ * -+ * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input() -+ * will fail, while __ip_route_output_key() will return success. The source -+ * address for __ip_route_output_key() is set to zero, so __ip_route_output_key -+ * thinks we're handling a locally generated packet and won't care -+ * if IP forwarding is allowed. We send a warning message to the users's -+ * log telling her to put IP forwarding on. -+ * -+ * ip_route_input() will also fail if there is no route available. -+ * In that case we just drop the packet. -+ * -+ * --Lennert, 20020411 -+ * --Bart, 20020416 (updated) -+ * --Bart, 20021007 (updated) -+ */ ++ {0, "INPUT", 0, EBT_ACCEPT, 0}, ++ {0, "FORWARD", 0, EBT_ACCEPT, 0}, ++ {0, "OUTPUT", 0, EBT_ACCEPT, 0} ++}; + -+static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) ++static struct ebt_replace initial_table = +{ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug |= (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_FORWARD); -+#endif -+ -+ if (skb->pkt_type == PACKET_OTHERHOST) { -+ skb->pkt_type = PACKET_HOST; -+ skb->nf_bridge->mask |= BRNF_PKT_TYPE; -+ } -+ skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; -+ -+ skb->dev = bridge_parent(skb->dev); -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_pull(skb, VLAN_HLEN); -+ skb->nh.raw += VLAN_HLEN; -+ } -+ skb->dst->output(skb); -+ return 0; -+} ++ "filter", FILTER_VALID_HOOKS, 0, 3 * sizeof(struct ebt_entries), ++ { [NF_BR_LOCAL_IN]&initial_chains[0], [NF_BR_FORWARD]&initial_chains[1], ++ [NF_BR_LOCAL_OUT]&initial_chains[2] }, 0, NULL, (char *)initial_chains ++}; + -+static int br_nf_pre_routing_finish(struct sk_buff *skb) ++static int check(const struct ebt_table_info *info, unsigned int valid_hooks) +{ -+ struct net_device *dev = skb->dev; -+ struct iphdr *iph = skb->nh.iph; -+ struct nf_bridge_info *nf_bridge = skb->nf_bridge; -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING); -+#endif -+ -+ if (nf_bridge->mask & BRNF_PKT_TYPE) { -+ skb->pkt_type = PACKET_OTHERHOST; -+ nf_bridge->mask ^= BRNF_PKT_TYPE; -+ } -+ nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; -+ -+ if (dnat_took_place(skb)) { -+ if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, -+ dev)) { -+ struct rtable *rt; -+ -+ if (!ip_route_output(&rt, iph->daddr, 0, iph->tos, 0)) { -+ /* Bridged-and-DNAT'ed traffic doesn't -+ * require ip_forwarding. -+ */ -+ if (((struct dst_entry *)rt)->dev == dev) { -+ skb->dst = (struct dst_entry *)rt; -+ goto bridged_dnat; -+ } -+ __br_dnat_complain(); -+ dst_release((struct dst_entry *)rt); -+ } -+ kfree_skb(skb); -+ return 0; -+ } else { -+ if (skb->dst->dev == dev) { -+bridged_dnat: -+ /* Tell br_nf_local_out this is a -+ * bridged frame -+ */ -+ nf_bridge->mask |= BRNF_BRIDGED_DNAT; -+ skb->dev = nf_bridge->physindev; -+ if (skb->protocol == -+ __constant_htons(ETH_P_8021Q)) { -+ skb_push(skb, VLAN_HLEN); -+ skb->nh.raw -= VLAN_HLEN; -+ } -+ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, -+ skb, skb->dev, NULL, -+ br_nf_pre_routing_finish_bridge, -+ 1); -+ return 0; -+ } -+ memcpy(skb->mac.ethernet->h_dest, dev->dev_addr, -+ ETH_ALEN); -+ skb->pkt_type = PACKET_HOST; -+ } -+ } else { -+ skb->dst = (struct dst_entry *)&__fake_rtable; -+ dst_hold(skb->dst); -+ } -+ -+ skb->dev = nf_bridge->physindev; -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_push(skb, VLAN_HLEN); -+ skb->nh.raw -= VLAN_HLEN; -+ } -+ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, -+ br_handle_frame_finish, 1); -+ ++ if (valid_hooks & ~FILTER_VALID_HOOKS) ++ return -EINVAL; + return 0; +} + -+/* Some common code for IPv4/IPv6 */ -+static void setup_pre_routing(struct sk_buff *skb) -+{ -+ struct nf_bridge_info *nf_bridge = skb->nf_bridge; -+ -+ if (skb->pkt_type == PACKET_OTHERHOST) { -+ skb->pkt_type = PACKET_HOST; -+ nf_bridge->mask |= BRNF_PKT_TYPE; -+ } -+ -+ nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; -+ nf_bridge->physindev = skb->dev; -+ skb->dev = bridge_parent(skb->dev); -+} -+ -+/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */ -+static int check_hbh_len(struct sk_buff *skb) -+{ -+ unsigned char *raw = (u8*)(skb->nh.ipv6h+1); -+ u32 pkt_len; -+ int off = raw - skb->nh.raw; -+ int len = (raw[1]+1)<<3; -+ -+ if ((raw + len) - skb->data > skb_headlen(skb)) -+ goto bad; -+ -+ off += 2; -+ len -= 2; -+ -+ while (len > 0) { -+ int optlen = raw[off+1]+2; -+ -+ switch (skb->nh.raw[off]) { -+ case IPV6_TLV_PAD0: -+ optlen = 1; -+ break; -+ -+ case IPV6_TLV_PADN: -+ break; -+ -+ case IPV6_TLV_JUMBO: -+ if (skb->nh.raw[off+1] != 4 || (off&3) != 2) -+ goto bad; -+ -+ pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2)); -+ -+ if (pkt_len > skb->len - sizeof(struct ipv6hdr)) -+ goto bad; -+ if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { -+ if (__pskb_trim(skb, -+ pkt_len + sizeof(struct ipv6hdr))) -+ goto bad; -+ if (skb->ip_summed == CHECKSUM_HW) -+ skb->ip_summed = CHECKSUM_NONE; -+ } -+ break; -+ default: -+ if (optlen > len) -+ goto bad; -+ break; -+ } -+ off += optlen; -+ len -= optlen; -+ } -+ if (len == 0) -+ return 0; -+bad: -+ return -1; -+ -+} ++static struct ebt_table frame_filter = ++{ ++ {NULL, NULL}, "filter", &initial_table, FILTER_VALID_HOOKS, ++ RW_LOCK_UNLOCKED, check, NULL ++}; + -+/* Replicate the checks that IPv6 does on packet reception and pass the packet -+ * to ip6tables, which doesn't support NAT, so things are fairly simple. */ -+static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, -+ struct sk_buff *skb, const struct net_device *in, ++static unsigned int ++ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in, + const struct net_device *out, int (*okfn)(struct sk_buff *)) +{ -+ struct ipv6hdr *hdr; -+ u32 pkt_len; -+ struct nf_bridge_info *nf_bridge; -+ -+ if (skb->len < sizeof(struct ipv6hdr)) -+ goto inhdr_error; -+ -+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) -+ goto inhdr_error; -+ -+ hdr = skb->nh.ipv6h; -+ -+ if (hdr->version != 6) -+ goto inhdr_error; -+ -+ pkt_len = ntohs(hdr->payload_len); -+ -+ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { -+ if (pkt_len + sizeof(struct ipv6hdr) > skb->len) -+ goto inhdr_error; -+ if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { -+ if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))) -+ goto inhdr_error; -+ if (skb->ip_summed == CHECKSUM_HW) -+ skb->ip_summed = CHECKSUM_NONE; -+ } -+ } -+ if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) -+ goto inhdr_error; -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING); -+#endif -+ if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) -+ return NF_DROP; -+ setup_pre_routing(skb); -+ -+ NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, -+ br_nf_pre_routing_finish_ipv6); -+ -+ return NF_STOLEN; -+ -+inhdr_error: -+ return NF_DROP; -+} -+ -+/* Direct IPv6 traffic to br_nf_pre_routing_ipv6. -+ * Replicate the checks that IPv4 does on packet reception. -+ * Set skb->dev to the bridge device (i.e. parent of the -+ * receiving device) to make netfilter happy, the REDIRECT -+ * target in particular. Save the original destination IP -+ * address to be able to detect DNAT afterwards. -+ */ -+static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) -+{ -+ struct iphdr *iph; -+ __u32 len; -+ struct sk_buff *skb = *pskb; -+ struct nf_bridge_info *nf_bridge; -+ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *) -+ ((*pskb)->mac.ethernet); -+ -+ if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) { -+#ifdef CONFIG_SYSCTL -+ if (!brnf_call_ip6tables) -+ return NF_ACCEPT; -+#endif -+ if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) -+ goto out; -+ -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_pull(skb, VLAN_HLEN); -+ (skb)->nh.raw += VLAN_HLEN; -+ } -+ return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); -+ } -+ -+#ifdef CONFIG_SYSCTL -+ if (!brnf_call_iptables) -+ return NF_ACCEPT; -+#endif -+ -+ if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP) -+ return NF_ACCEPT; -+ if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) -+ goto out; -+ -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_pull(skb, VLAN_HLEN); -+ (skb)->nh.raw += VLAN_HLEN; -+ } -+ -+ if (!pskb_may_pull(skb, sizeof(struct iphdr))) -+ goto inhdr_error; -+ -+ iph = skb->nh.iph; -+ if (iph->ihl < 5 || iph->version != 4) -+ goto inhdr_error; -+ -+ if (!pskb_may_pull(skb, 4*iph->ihl)) -+ goto inhdr_error; -+ -+ iph = skb->nh.iph; -+ if (ip_fast_csum((__u8 *)iph, iph->ihl) != 0) -+ goto inhdr_error; -+ -+ len = ntohs(iph->tot_len); -+ if (skb->len < len || len < 4*iph->ihl) -+ goto inhdr_error; -+ -+ if (skb->len > len) { -+ __pskb_trim(skb, len); -+ if (skb->ip_summed == CHECKSUM_HW) -+ skb->ip_summed = CHECKSUM_NONE; -+ } -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING); -+#endif -+ if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) -+ return NF_DROP; -+ -+ setup_pre_routing(skb); -+ store_orig_dstaddr(skb); -+ -+ NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, -+ br_nf_pre_routing_finish); -+ -+ return NF_STOLEN; -+ -+inhdr_error: -+// IP_INC_STATS_BH(IpInHdrErrors); -+out: -+ return NF_DROP; ++ return ebt_do_table(hook, pskb, in, out, &frame_filter); +} + ++static struct nf_hook_ops ebt_ops_filter[] = { ++ { { NULL, NULL }, ebt_hook, PF_BRIDGE, NF_BR_LOCAL_IN, ++ NF_BR_PRI_FILTER_BRIDGED}, ++ { { NULL, NULL }, ebt_hook, PF_BRIDGE, NF_BR_FORWARD, ++ NF_BR_PRI_FILTER_BRIDGED}, ++ { { NULL, NULL }, ebt_hook, PF_BRIDGE, NF_BR_LOCAL_OUT, ++ NF_BR_PRI_FILTER_OTHER} ++}; + -+/* PF_BRIDGE/LOCAL_IN ************************************************/ -+/* The packet is locally destined, which requires a real -+ * dst_entry, so detach the fake one. On the way up, the -+ * packet would pass through PRE_ROUTING again (which already -+ * took place when the packet entered the bridge), but we -+ * register an IPv4 PRE_ROUTING 'sabotage' hook that will -+ * prevent this from happening. -+ */ -+static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) -+{ -+ struct sk_buff *skb = *pskb; -+ -+ if (skb->dst == (struct dst_entry *)&__fake_rtable) { -+ dst_release(skb->dst); -+ skb->dst = NULL; -+ } -+ -+ return NF_ACCEPT; -+} -+ -+/* PF_BRIDGE/FORWARD *************************************************/ -+static int br_nf_forward_finish(struct sk_buff *skb) ++static int __init init(void) +{ -+ struct nf_bridge_info *nf_bridge = skb->nf_bridge; -+ struct net_device *in; -+/* struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);*/ -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_BR_FORWARD); -+#endif ++ int i, j, ret; + -+/* if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {*/ -+ in = nf_bridge->physindev; -+ if (nf_bridge->mask & BRNF_PKT_TYPE) { -+ skb->pkt_type = PACKET_OTHERHOST; -+ nf_bridge->mask ^= BRNF_PKT_TYPE; -+ } -+/* } else { -+ in = *((struct net_device **)(skb->cb)); -+ }*/ -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_push(skb, VLAN_HLEN); -+ skb->nh.raw -= VLAN_HLEN; -+ } -+ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, -+ skb->dev, br_forward_finish, 1); -+ return 0; ++ ret = ebt_register_table(&frame_filter); ++ if (ret < 0) ++ return ret; ++ for (i = 0; i < sizeof(ebt_ops_filter) / sizeof(ebt_ops_filter[0]); i++) ++ if ((ret = nf_register_hook(&ebt_ops_filter[i])) < 0) ++ goto cleanup; ++ return ret; ++cleanup: ++ for (j = 0; j < i; j++) ++ nf_unregister_hook(&ebt_ops_filter[j]); ++ ebt_unregister_table(&frame_filter); ++ return ret; +} + -+/* This is the 'purely bridged' case. For IP, we pass the packet to -+ * netfilter with indev and outdev set to the bridge device, -+ * but we are still able to filter on the 'real' indev/outdev -+ * because of the ipt_physdev.c module. For ARP, indev and outdev are the -+ * bridge ports. -+ */ -+static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) ++static void __exit fini(void) +{ -+ struct sk_buff *skb = *pskb; -+ struct nf_bridge_info *nf_bridge; -+ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); -+ int pf; -+ -+ if (!skb->nf_bridge) -+ return NF_ACCEPT; -+ -+ if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) -+ pf = PF_INET; -+ else -+ pf = PF_INET6; -+ -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_pull(*pskb, VLAN_HLEN); -+ (*pskb)->nh.raw += VLAN_HLEN; -+ } -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_BR_FORWARD); -+#endif -+ nf_bridge = skb->nf_bridge; -+ if (skb->pkt_type == PACKET_OTHERHOST) { -+ skb->pkt_type = PACKET_HOST; -+ nf_bridge->mask |= BRNF_PKT_TYPE; -+ } -+ -+ /* The physdev module checks on this */ -+ nf_bridge->mask |= BRNF_BRIDGED; -+ nf_bridge->physoutdev = skb->dev; -+ -+ NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), -+ bridge_parent(out), br_nf_forward_finish); ++ int i; + -+ return NF_STOLEN; ++ for (i = 0; i < sizeof(ebt_ops_filter) / sizeof(ebt_ops_filter[0]); i++) ++ nf_unregister_hook(&ebt_ops_filter[i]); ++ ebt_unregister_table(&frame_filter); +} + ++module_init(init); ++module_exit(fini); ++EXPORT_NO_SYMBOLS; ++MODULE_LICENSE("GPL"); +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebtable_nat.c 2005-03-14 00:00:29.000000000 +0100 +@@ -0,0 +1,96 @@ +/* -+static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) -+{ -+ struct sk_buff *skb = *pskb; -+ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); -+ struct net_device **d = (struct net_device **)(skb->cb); -+ -+ if (!brnf_call_arptables) -+ return NF_ACCEPT; -+ -+ if (skb->protocol != __constant_htons(ETH_P_ARP)) { -+ if (!IS_VLAN_ARP) -+ return NF_ACCEPT; -+ skb_pull(*pskb, VLAN_HLEN); -+ (*pskb)->nh.raw += VLAN_HLEN; -+ } -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_BR_FORWARD); -+#endif -+ -+ if (skb->nh.arph->ar_pln != 4) { -+ if (IS_VLAN_ARP) { -+ skb_push(*pskb, VLAN_HLEN); -+ (*pskb)->nh.raw -= VLAN_HLEN; -+ } -+ return NF_ACCEPT; -+ } -+ *d = (struct net_device *)in; -+ NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in, -+ (struct net_device *)out, br_nf_forward_finish); -+ -+ return NF_STOLEN; -+} -+*/ -+ -+/* PF_BRIDGE/LOCAL_OUT ***********************************************/ -+static int br_nf_local_out_finish(struct sk_buff *skb) -+{ -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug &= ~(1 << NF_BR_LOCAL_OUT); -+#endif -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_push(skb, VLAN_HLEN); -+ skb->nh.raw -= VLAN_HLEN; -+ } -+ -+ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, -+ br_forward_finish, NF_BR_PRI_FIRST + 1); -+ -+ return 0; -+} -+ -+ -+/* This function sees both locally originated IP packets and forwarded -+ * IP packets (in both cases the destination device is a bridge -+ * device). It also sees bridged-and-DNAT'ed packets. -+ * To be able to filter on the physical bridge devices (with the ipt_physdev.c -+ * module), we steal packets destined to a bridge device away from the -+ * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later, -+ * when we have determined the real output device. This is done in here. ++ * ebtable_nat ++ * ++ * Authors: ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * ++ * April, 2002 + * -+ * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged -+ * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward() -+ * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority -+ * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor -+ * will be executed. -+ * Otherwise, if nf_bridge->physindev is NULL, the bridge-nf code never touched -+ * this packet before, and so the packet was locally originated. We fake -+ * the PF_INET/LOCAL_OUT hook. -+ * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed, -+ * so we fake the PF_INET/FORWARD hook. ipv4_sabotage_out() makes sure -+ * even routed packets that didn't arrive on a bridge interface have their -+ * nf_bridge->physindev set. + */ + -+static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) -+{ -+ struct net_device *realindev, *realoutdev; -+ struct sk_buff *skb = *pskb; -+ struct nf_bridge_info *nf_bridge; -+ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); -+ int pf; -+ -+ if (!skb->nf_bridge) -+ return NF_ACCEPT; -+ -+ if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) -+ pf = PF_INET; -+ else -+ pf = PF_INET6; -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ /* Sometimes we get packets with NULL ->dst here (for example, -+ * running a dhcp client daemon triggers this). This should now -+ * be fixed, but let's keep the check around. */ -+ if (skb->dst == NULL) { -+ printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); -+ return NF_ACCEPT; -+ } -+#endif -+ -+ nf_bridge = skb->nf_bridge; -+ nf_bridge->physoutdev = skb->dev; -+ realindev = nf_bridge->physindev; -+ -+ /* Bridged, take PF_BRIDGE/FORWARD. -+ * (see big note in front of br_nf_pre_routing_finish) -+ */ -+ if (nf_bridge->mask & BRNF_BRIDGED_DNAT) { -+ if (nf_bridge->mask & BRNF_PKT_TYPE) { -+ skb->pkt_type = PACKET_OTHERHOST; -+ nf_bridge->mask ^= BRNF_PKT_TYPE; -+ } -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_push(skb, VLAN_HLEN); -+ skb->nh.raw -= VLAN_HLEN; -+ } -+ -+ NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, -+ skb->dev, br_forward_finish); -+ goto out; -+ } -+ realoutdev = bridge_parent(skb->dev); -+ -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+ /* iptables should match -o br0.x */ -+ if (nf_bridge->netoutdev) -+ realoutdev = nf_bridge->netoutdev; -+#endif -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_pull(skb, VLAN_HLEN); -+ (*pskb)->nh.raw += VLAN_HLEN; -+ } -+ /* IP forwarded traffic has a physindev, locally -+ * generated traffic hasn't. -+ */ -+ if (realindev != NULL) { -+ if (((nf_bridge->mask & BRNF_DONT_TAKE_PARENT) == 0) && -+ has_bridge_parent(realindev)) -+ realindev = bridge_parent(realindev); -+ NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev, -+ realoutdev, okfn, -+ NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1); -+ } else { -+#ifdef CONFIG_NETFILTER_DEBUG -+ skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT); -+#endif -+ -+ NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev, -+ realoutdev, okfn, -+ NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1); -+ } -+ -+out: -+ return NF_STOLEN; -+} -+ ++#include <linux/netfilter_bridge/ebtables.h> ++#include <linux/module.h> ++#define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \ ++ (1 << NF_BR_POST_ROUTING)) + -+/* PF_BRIDGE/POST_ROUTING ********************************************/ -+static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) ++static struct ebt_entries initial_chains[] = +{ -+ struct sk_buff *skb = *pskb; -+ struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; -+ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); -+ struct net_device *realoutdev = bridge_parent(skb->dev); -+ int pf; -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ /* Be very paranoid. This probably won't happen anymore, but let's -+ * keep the check just to be sure... */ -+ if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { -+ printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " -+ "bad mac.raw pointer."); -+ goto print_error; -+ } -+#endif -+ -+ if (!nf_bridge) -+ return NF_ACCEPT; -+ -+ if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) -+ pf = PF_INET; -+ else -+ pf = PF_INET6; -+ -+ /* Sometimes we get packets with NULL ->dst here (for example, -+ * running a dhcp client daemon triggers this). -+ */ -+ if (skb->dst == NULL) -+ return NF_ACCEPT; -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+ /* Sometimes we get packets with NULL ->dst here (for example, -+ * running a dhcp client daemon triggers this). This should now -+ * be fixed, but let's keep the check around. -+ */ -+ if (skb->dst == NULL) { -+ printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); -+ goto print_error; -+ } -+ -+ skb->nf_debug ^= (1 << NF_IP_POST_ROUTING); -+#endif -+ -+ /* We assume any code from br_dev_queue_push_xmit onwards doesn't care -+ * about the value of skb->pkt_type. -+ */ -+ if (skb->pkt_type == PACKET_OTHERHOST) { -+ skb->pkt_type = PACKET_HOST; -+ nf_bridge->mask |= BRNF_PKT_TYPE; -+ } -+ -+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { -+ skb_pull(skb, VLAN_HLEN); -+ skb->nh.raw += VLAN_HLEN; -+ } -+ -+ nf_bridge_save_header(skb); -+ -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+ if (nf_bridge->netoutdev) -+ realoutdev = nf_bridge->netoutdev; -+#endif -+ NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, -+ realoutdev, br_dev_queue_push_xmit); -+ -+ return NF_STOLEN; -+ -+#ifdef CONFIG_NETFILTER_DEBUG -+print_error: -+ if (skb->dev != NULL) { -+ printk("[%s]", skb->dev->name); -+ if (has_bridge_parent(skb->dev)) -+ printk("[%s]", bridge_parent(skb->dev)->name); -+ } -+ printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, -+ skb->data); -+ return NF_ACCEPT; -+#endif -+} -+ -+ -+/* IPv4/SABOTAGE *****************************************************/ ++ {0, "PREROUTING", 0, EBT_ACCEPT, 0}, ++ {0, "OUTPUT", 0, EBT_ACCEPT, 0}, ++ {0, "POSTROUTING", 0, EBT_ACCEPT, 0} ++}; + -+/* Don't hand locally destined packets to PF_INET/PRE_ROUTING -+ * for the second time. -+ */ -+static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) ++static struct ebt_replace initial_table = +{ -+ if ((*pskb)->nf_bridge && -+ !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { -+ okfn(*pskb); -+ return NF_STOLEN; -+ } -+ -+ return NF_ACCEPT; -+} ++ "nat", NAT_VALID_HOOKS, 0, 3 * sizeof(struct ebt_entries), ++ { [NF_BR_PRE_ROUTING]&initial_chains[0], [NF_BR_LOCAL_OUT]&initial_chains[1], ++ [NF_BR_POST_ROUTING]&initial_chains[2] }, 0, NULL, (char *)initial_chains ++}; + -+/* Postpone execution of PF_INET/FORWARD, PF_INET/LOCAL_OUT -+ * and PF_INET/POST_ROUTING until we have done the forwarding -+ * decision in the bridge code and have determined skb->physoutdev. -+ */ -+static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, -+ const struct net_device *in, const struct net_device *out, -+ int (*okfn)(struct sk_buff *)) ++static int check(const struct ebt_table_info *info, unsigned int valid_hooks) +{ -+ struct sk_buff *skb = *pskb; -+ -+ if ((out->hard_start_xmit == br_dev_xmit && -+ okfn != br_nf_forward_finish && -+ okfn != br_nf_local_out_finish && -+ okfn != br_dev_queue_push_xmit) -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+ || ((out->priv_flags & IFF_802_1Q_VLAN) && -+ VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) -+#endif -+ ) { -+ struct nf_bridge_info *nf_bridge; -+ -+ if (!skb->nf_bridge) { -+#ifdef CONFIG_SYSCTL -+ /* This code is executed while in the IP(v6) stack, -+ the version should be 4 or 6. We can't use -+ skb->protocol because that isn't set on -+ PF_INET(6)/LOCAL_OUT. */ -+ struct iphdr *ip = skb->nh.iph; -+ -+ if (ip->version == 4 && !brnf_call_iptables) -+ return NF_ACCEPT; -+ else if (ip->version == 6 && !brnf_call_ip6tables) -+ return NF_ACCEPT; -+#endif -+ if (hook == NF_IP_POST_ROUTING) -+ return NF_ACCEPT; -+ if (!nf_bridge_alloc(skb)) -+ return NF_DROP; -+ } -+ -+ nf_bridge = skb->nf_bridge; -+ -+ /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we -+ * will need the indev then. For a brouter, the real indev -+ * can be a bridge port, so we make sure br_nf_local_out() -+ * doesn't use the bridge parent of the indev by using -+ * the BRNF_DONT_TAKE_PARENT mask. -+ */ -+ if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) { -+ nf_bridge->mask &= BRNF_DONT_TAKE_PARENT; -+ nf_bridge->physindev = (struct net_device *)in; -+ } -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+ /* the iptables outdev is br0.x, not br0 */ -+ if (out->priv_flags & IFF_802_1Q_VLAN) -+ nf_bridge->netoutdev = (struct net_device *)out; -+#endif -+ okfn(skb); -+ return NF_STOLEN; -+ } -+ -+ return NF_ACCEPT; ++ if (valid_hooks & ~NAT_VALID_HOOKS) ++ return -EINVAL; ++ return 0; +} + -+/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent -+ * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input. -+ * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because -+ * ip_refrag() can return NF_STOLEN. -+ */ -+static struct nf_hook_ops br_nf_ops[] = { -+ { .hook = br_nf_pre_routing, -+ .pf = PF_BRIDGE, -+ .hooknum = NF_BR_PRE_ROUTING, -+ .priority = NF_BR_PRI_BRNF, }, -+ { .hook = br_nf_local_in, -+ .pf = PF_BRIDGE, -+ .hooknum = NF_BR_LOCAL_IN, -+ .priority = NF_BR_PRI_BRNF, }, -+ { .hook = br_nf_forward_ip, -+ .pf = PF_BRIDGE, -+ .hooknum = NF_BR_FORWARD, -+ .priority = NF_BR_PRI_BRNF /*- 1*/, }, -+/* { .hook = br_nf_forward_arp, -+ .pf = PF_BRIDGE, -+ .hooknum = NF_BR_FORWARD, -+ .priority = NF_BR_PRI_BRNF, },*/ -+ { .hook = br_nf_local_out, -+ .pf = PF_BRIDGE, -+ .hooknum = NF_BR_LOCAL_OUT, -+ .priority = NF_BR_PRI_FIRST, }, -+ { .hook = br_nf_post_routing, -+ .pf = PF_BRIDGE, -+ .hooknum = NF_BR_POST_ROUTING, -+ .priority = NF_BR_PRI_LAST, }, -+ { .hook = ip_sabotage_in, -+ .pf = PF_INET, -+ .hooknum = NF_IP_PRE_ROUTING, -+ .priority = NF_IP_PRI_FIRST, }, -+ { .hook = ip_sabotage_in, -+ .pf = PF_INET6, -+ .hooknum = NF_IP6_PRE_ROUTING, -+ .priority = NF_IP6_PRI_FIRST, }, -+ { .hook = ip_sabotage_out, -+ .pf = PF_INET, -+ .hooknum = NF_IP_FORWARD, -+ .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, }, -+ { .hook = ip_sabotage_out, -+ .pf = PF_INET6, -+ .hooknum = NF_IP6_FORWARD, -+ .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, }, -+ { .hook = ip_sabotage_out, -+ .pf = PF_INET, -+ .hooknum = NF_IP_LOCAL_OUT, -+ .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, }, -+ { .hook = ip_sabotage_out, -+ .pf = PF_INET6, -+ .hooknum = NF_IP6_LOCAL_OUT, -+ .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, }, -+ { .hook = ip_sabotage_out, -+ .pf = PF_INET, -+ .hooknum = NF_IP_POST_ROUTING, -+ .priority = NF_IP_PRI_FIRST, }, -+ { .hook = ip_sabotage_out, -+ .pf = PF_INET6, -+ .hooknum = NF_IP6_POST_ROUTING, -+ .priority = NF_IP6_PRI_FIRST, }, ++static struct ebt_table frame_nat = ++{ ++ {NULL, NULL}, "nat", &initial_table, NAT_VALID_HOOKS, ++ RW_LOCK_UNLOCKED, check, NULL +}; + -+#ifdef CONFIG_SYSCTL -+static -+int brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp, -+ void *buffer, size_t *lenp) ++static unsigned int ++ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in ++ , const struct net_device *out, int (*okfn)(struct sk_buff *)) +{ -+ int ret; -+ -+ ret = proc_dointvec(ctl, write, filp, buffer, lenp); -+ -+ if (write && *(int *)(ctl->data)) -+ *(int *)(ctl->data) = 1; -+ return ret; ++ return ebt_do_table(hook, pskb, in, out, &frame_nat); +} + -+static ctl_table brnf_table[] = { -+ { -+ .ctl_name = NET_BRIDGE_NF_CALL_ARPTABLES, -+ .procname = "bridge-nf-call-arptables", -+ .data = &brnf_call_arptables, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = &brnf_sysctl_call_tables, -+ }, -+ { -+ .ctl_name = NET_BRIDGE_NF_CALL_IPTABLES, -+ .procname = "bridge-nf-call-iptables", -+ .data = &brnf_call_iptables, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = &brnf_sysctl_call_tables, -+ }, -+ { -+ .ctl_name = NET_BRIDGE_NF_CALL_IP6TABLES, -+ .procname = "bridge-nf-call-ip6tables", -+ .data = &brnf_call_ip6tables, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = &brnf_sysctl_call_tables, -+ }, -+ { -+ .ctl_name = NET_BRIDGE_NF_FILTER_VLAN_TAGGED, -+ .procname = "bridge-nf-filter-vlan-tagged", -+ .data = &brnf_filter_vlan_tagged, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = &brnf_sysctl_call_tables, -+ }, -+ { .ctl_name = 0 } -+}; -+ -+static ctl_table brnf_bridge_table[] = { -+ { -+ .ctl_name = NET_BRIDGE, -+ .procname = "bridge", -+ .mode = 0555, -+ .child = brnf_table, -+ }, -+ { .ctl_name = 0 } -+}; ++static unsigned int ++ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in ++ , const struct net_device *out, int (*okfn)(struct sk_buff *)) ++{ ++ return ebt_do_table(hook, pskb, in, out, &frame_nat); ++} + -+static ctl_table brnf_net_table[] = { -+ { -+ .ctl_name = CTL_NET, -+ .procname = "net", -+ .mode = 0555, -+ .child = brnf_bridge_table, -+ }, -+ { .ctl_name = 0 } ++static struct nf_hook_ops ebt_ops_nat[] = { ++ { { NULL, NULL }, ebt_nat_dst, PF_BRIDGE, NF_BR_LOCAL_OUT, ++ NF_BR_PRI_NAT_DST_OTHER}, ++ { { NULL, NULL }, ebt_nat_src, PF_BRIDGE, NF_BR_POST_ROUTING, ++ NF_BR_PRI_NAT_SRC}, ++ { { NULL, NULL }, ebt_nat_dst, PF_BRIDGE, NF_BR_PRE_ROUTING, ++ NF_BR_PRI_NAT_DST_BRIDGED}, +}; -+#endif + -+int br_netfilter_init(void) ++static int __init init(void) +{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) { -+ int ret; -+ -+ if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0) -+ continue; -+ -+ while (i--) -+ nf_unregister_hook(&br_nf_ops[i]); ++ int i, ret, j; + ++ ret = ebt_register_table(&frame_nat); ++ if (ret < 0) + return ret; -+ } -+ -+#ifdef CONFIG_SYSCTL -+ brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0); -+ if (brnf_sysctl_header == NULL) { -+ printk(KERN_WARNING "br_netfilter: can't register to sysctl.\n"); -+ for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) -+ nf_unregister_hook(&br_nf_ops[i]); -+ return -EFAULT; -+ } -+#endif -+ -+ printk(KERN_NOTICE "Bridge firewalling registered\n"); -+ -+ return 0; ++ for (i = 0; i < sizeof(ebt_ops_nat) / sizeof(ebt_ops_nat[0]); i++) ++ if ((ret = nf_register_hook(&ebt_ops_nat[i])) < 0) ++ goto cleanup; ++ return ret; ++cleanup: ++ for (j = 0; j < i; j++) ++ nf_unregister_hook(&ebt_ops_nat[j]); ++ ebt_unregister_table(&frame_nat); ++ return ret; +} + -+void br_netfilter_fini(void) ++static void __exit fini(void) +{ + int i; + -+ for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--) -+ nf_unregister_hook(&br_nf_ops[i]); -+#ifdef CONFIG_SYSCTL -+ unregister_sysctl_table(brnf_sysctl_header); -+#endif -+ ++ for (i = 0; i < sizeof(ebt_ops_nat) / sizeof(ebt_ops_nat[0]); i++) ++ nf_unregister_hook(&ebt_ops_nat[i]); ++ ebt_unregister_table(&frame_nat); +} -diff -Nur linux-mips-cvs/net/bridge/br_private.h linux-ebtables/net/bridge/br_private.h ---- linux-mips-cvs/net/bridge/br_private.h 2004-08-14 20:39:04.000000000 +0200 -+++ linux-ebtables/net/bridge/br_private.h 2005-02-07 05:52:50.000000000 +0100 -@@ -143,8 +143,10 @@ - /* br_forward.c */ - extern void br_deliver(struct net_bridge_port *to, - struct sk_buff *skb); -+extern int br_dev_queue_push_xmit(struct sk_buff *skb); - extern void br_forward(struct net_bridge_port *to, - struct sk_buff *skb); -+extern int br_forward_finish(struct sk_buff *skb); - extern void br_flood_deliver(struct net_bridge *br, - struct sk_buff *skb, - int clone); -@@ -165,7 +167,8 @@ - int *ifindices); - - /* br_input.c */ --extern void br_handle_frame(struct sk_buff *skb); -+extern int br_handle_frame_finish(struct sk_buff *skb); -+extern int br_handle_frame(struct sk_buff *skb); - - /* br_ioctl.c */ - extern int br_ioctl(struct net_bridge *br, -@@ -175,6 +178,10 @@ - unsigned long arg2); - extern int br_ioctl_deviceless_stub(unsigned long arg); - -+/* br_netfilter.c */ -+extern int br_netfilter_init(void); -+extern void br_netfilter_fini(void); + - /* br_stp.c */ - extern int br_is_root_bridge(struct net_bridge *br); - extern struct net_bridge_port *br_get_port(struct net_bridge *br, -diff -Nur linux-mips-cvs/net/bridge/netfilter/Config.in linux-ebtables/net/bridge/netfilter/Config.in ---- linux-mips-cvs/net/bridge/netfilter/Config.in 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/Config.in 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,23 @@ -+# -+# Bridge netfilter configuration -+# -+dep_tristate ' Bridge: ebtables' CONFIG_BRIDGE_NF_EBTABLES $CONFIG_BRIDGE -+dep_tristate ' ebt: filter table support' CONFIG_BRIDGE_EBT_T_FILTER $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: nat table support' CONFIG_BRIDGE_EBT_T_NAT $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: broute table support' CONFIG_BRIDGE_EBT_BROUTE $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: log support' CONFIG_BRIDGE_EBT_LOG $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: ulog support' CONFIG_BRIDGE_EBT_LOG $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: IP filter support' CONFIG_BRIDGE_EBT_IPF $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: ARP filter support' CONFIG_BRIDGE_EBT_ARPF $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: among filter support' CONFIG_BRIDGE_EBT_AMONG $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: limit filter support' CONFIG_BRIDGE_EBT_LIMIT $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: 802.1Q VLAN filter support' CONFIG_BRIDGE_EBT_VLANF $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: 802.3 filter support' CONFIG_BRIDGE_EBT_802_3 $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: packet type filter support' CONFIG_BRIDGE_EBT_PKTTYPE $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: STP filter support' CONFIG_BRIDGE_EBT_STP $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: mark filter support' CONFIG_BRIDGE_EBT_MARKF $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: arp reply target support' CONFIG_BRIDGE_EBT_ARPREPLY $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: snat target support' CONFIG_BRIDGE_EBT_SNAT $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: dnat target support' CONFIG_BRIDGE_EBT_DNAT $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: redirect target support' CONFIG_BRIDGE_EBT_REDIRECT $CONFIG_BRIDGE_NF_EBTABLES -+dep_tristate ' ebt: mark target support' CONFIG_BRIDGE_EBT_MARK_T $CONFIG_BRIDGE_NF_EBTABLES -diff -Nur linux-mips-cvs/net/bridge/netfilter/Makefile linux-ebtables/net/bridge/netfilter/Makefile ---- linux-mips-cvs/net/bridge/netfilter/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/Makefile 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,34 @@ -+# -+# Makefile for the netfilter modules on top of bridging. -+# -+# Note! Dependencies are done automagically by 'make dep', which also -+# removes any old dependencies. DON'T put your own dependencies here -+# unless it's something special (ie not a .c file). -+# -+# Note 2! The CFLAGS definition is now in the main makefile... -+ -+O_TARGET := netfilter.o -+ -+export-objs := ebtables.o -+ -+obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o -+obj-$(CONFIG_BRIDGE_EBT_T_FILTER) += ebtable_filter.o -+obj-$(CONFIG_BRIDGE_EBT_T_NAT) += ebtable_nat.o -+obj-$(CONFIG_BRIDGE_EBT_BROUTE) += ebtable_broute.o -+obj-$(CONFIG_BRIDGE_EBT_802_3) += ebt_802_3.o -+obj-$(CONFIG_BRIDGE_EBT_ARPF) += ebt_arp.o -+obj-$(CONFIG_BRIDGE_EBT_AMONG) += ebt_among.o -+obj-$(CONFIG_BRIDGE_EBT_IPF) += ebt_ip.o -+obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o -+obj-$(CONFIG_BRIDGE_EBT_MARKF) += ebt_mark_m.o -+obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o -+obj-$(CONFIG_BRIDGE_EBT_STP) += ebt_stp.o -+obj-$(CONFIG_BRIDGE_EBT_VLANF) += ebt_vlan.o -+obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o -+obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_ulog.o -+obj-$(CONFIG_BRIDGE_EBT_ARPREPLY) += ebt_arpreply.o -+obj-$(CONFIG_BRIDGE_EBT_DNAT) += ebt_dnat.o -+obj-$(CONFIG_BRIDGE_EBT_MARK_T) += ebt_mark.o -+obj-$(CONFIG_BRIDGE_EBT_REDIRECT) += ebt_redirect.o -+obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o -+include $(TOPDIR)/Rules.make -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_802_3.c linux-ebtables/net/bridge/netfilter/ebt_802_3.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_802_3.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_802_3.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,74 @@ ++module_init(init); ++module_exit(fini); ++EXPORT_NO_SYMBOLS; ++MODULE_LICENSE("GPL"); +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebtable_broute.c 2005-03-14 00:00:29.000000000 +0100 +@@ -0,0 +1,79 @@ +/* -+ * 802_3 ++ * ebtable_broute + * -+ * Author: -+ * Chris Vitale csv@bluetail.com ++ * Authors: ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> + * -+ * May 2003 -+ * ++ * April, 2002 ++ * ++ * This table lets you choose between routing and bridging for frames ++ * entering on a bridge enslaved nic. This table is traversed before any ++ * other ebtables table. See net/bridge/br_input.c. + */ + +#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_802_3.h> +#include <linux/module.h> ++#include <linux/if_bridge.h> ++#include <linux/brlock.h> + -+static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *in, -+ const struct net_device *out, const void *data, unsigned int datalen) -+{ -+ struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; -+ struct ebt_802_3_hdr *hdr = (struct ebt_802_3_hdr *)skb->mac.ethernet; -+ uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; -+ -+ if (info->bitmask & EBT_802_3_SAP) { -+ if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP)) -+ return EBT_NOMATCH; -+ if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP)) -+ return EBT_NOMATCH; -+ } -+ -+ if (info->bitmask & EBT_802_3_TYPE) { -+ if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE)) -+ return EBT_NOMATCH; -+ if (FWINV(info->type != type, EBT_802_3_TYPE)) -+ return EBT_NOMATCH; -+ } -+ -+ return EBT_MATCH; -+} ++// EBT_ACCEPT means the frame will be bridged ++// EBT_DROP means the frame will be routed ++static struct ebt_entries initial_chain = ++ {0, "BROUTING", 0, EBT_ACCEPT, 0}; + -+static struct ebt_match filter_802_3; -+static int ebt_802_3_check(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *data, unsigned int datalen) ++static struct ebt_replace initial_table = +{ -+ struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; ++ "broute", 1 << NF_BR_BROUTING, 0, sizeof(struct ebt_entries), ++ { [NF_BR_BROUTING]&initial_chain}, 0, NULL, (char *)&initial_chain ++}; + -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_802_3_info))) -+ return -EINVAL; -+ if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK) ++static int check(const struct ebt_table_info *info, unsigned int valid_hooks) ++{ ++ if (valid_hooks & ~(1 << NF_BR_BROUTING)) + return -EINVAL; -+ + return 0; +} + -+static struct ebt_match filter_802_3 = ++static struct ebt_table broute_table = +{ -+ .name = EBT_802_3_MATCH, -+ .match = ebt_filter_802_3, -+ .check = ebt_802_3_check, -+ .me = THIS_MODULE, ++ {NULL, NULL}, "broute", &initial_table, 1 << NF_BR_BROUTING, ++ RW_LOCK_UNLOCKED, check, NULL +}; + ++static int ebt_broute(struct sk_buff **pskb) ++{ ++ int ret; ++ ++ ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL, ++ &broute_table); ++ if (ret == NF_DROP) ++ return 1; // route it ++ return 0; // bridge it ++} ++ +static int __init init(void) +{ -+ return ebt_register_match(&filter_802_3); ++ int ret; ++ ++ ret = ebt_register_table(&broute_table); ++ if (ret < 0) ++ return ret; ++ br_write_lock_bh(BR_NETPROTO_LOCK); ++ // see br_input.c ++ br_should_route_hook = ebt_broute; ++ br_write_unlock_bh(BR_NETPROTO_LOCK); ++ return ret; +} + +static void __exit fini(void) +{ -+ ebt_unregister_match(&filter_802_3); ++ br_write_lock_bh(BR_NETPROTO_LOCK); ++ br_should_route_hook = NULL; ++ br_write_unlock_bh(BR_NETPROTO_LOCK); ++ ebt_unregister_table(&broute_table); +} + +module_init(init); +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_among.c linux-ebtables/net/bridge/netfilter/ebt_among.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_among.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_among.c 2005-02-07 05:52:50.000000000 +0100 +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_among.c 2005-03-14 00:00:29.000000000 +0100 @@ -0,0 +1,223 @@ +/* + * ebt_among @@ -3804,162 +980,112 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_among.c linux-ebtables/net/bri +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_arp.c linux-ebtables/net/bridge/netfilter/ebt_arp.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_arp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_arp.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,149 @@ +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_limit.c 2005-03-14 00:00:29.000000000 +0100 +@@ -0,0 +1,101 @@ +/* -+ * ebt_arp ++ * ebt_limit + * + * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> -+ * Tim Gardner <timg@tpi.com> ++ * Tom Marshall <tommy@home.tig-grr.com> + * -+ * April, 2002 ++ * Mostly copied from netfilter's ipt_limit.c, see that file for explanation ++ * ++ * September, 2003 + * + */ + +#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_arp.h> -+#include <linux/if_arp.h> -+#include <linux/if_ether.h> ++#include <linux/netfilter_bridge/ebt_limit.h> +#include <linux/module.h> + -+static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in, -+ const struct net_device *out, const void *data, unsigned int datalen) -+{ -+ struct ebt_arp_info *info = (struct ebt_arp_info *)data; ++#include <linux/netdevice.h> ++#include <linux/spinlock.h> + -+ if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode != -+ ((*skb).nh.arph)->ar_op, EBT_ARP_OPCODE)) -+ return EBT_NOMATCH; -+ if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype != -+ ((*skb).nh.arph)->ar_hrd, EBT_ARP_HTYPE)) -+ return EBT_NOMATCH; -+ if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype != -+ ((*skb).nh.arph)->ar_pro, EBT_ARP_PTYPE)) -+ return EBT_NOMATCH; ++static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED; + -+ if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) -+ { -+ uint32_t arp_len = sizeof(struct arphdr) + -+ (2 * (((*skb).nh.arph)->ar_hln)) + -+ (2 * (((*skb).nh.arph)->ar_pln)); -+ uint32_t dst; -+ uint32_t src; ++#define CREDITS_PER_JIFFY 128 + -+ // Make sure the packet is long enough. -+ if ((((*skb).nh.raw) + arp_len) > (*skb).tail) -+ return EBT_NOMATCH; -+ // IPv4 addresses are always 4 bytes. -+ if (((*skb).nh.arph)->ar_pln != sizeof(uint32_t)) -+ return EBT_NOMATCH; ++static int ebt_limit_match(const struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, const void *data, unsigned int datalen) ++{ ++ struct ebt_limit_info *info = (struct ebt_limit_info *)data; ++ unsigned long now = jiffies; + -+ if (info->bitmask & EBT_ARP_SRC_IP) { -+ memcpy(&src, ((*skb).nh.raw) + sizeof(struct arphdr) + -+ ((*skb).nh.arph)->ar_hln, sizeof(uint32_t)); -+ if (FWINV(info->saddr != (src & info->smsk), -+ EBT_ARP_SRC_IP)) -+ return EBT_NOMATCH; -+ } ++ spin_lock_bh(&limit_lock); ++ info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY; ++ if (info->credit > info->credit_cap) ++ info->credit = info->credit_cap; + -+ if (info->bitmask & EBT_ARP_DST_IP) { -+ memcpy(&dst, ((*skb).nh.raw)+sizeof(struct arphdr) + -+ (2*(((*skb).nh.arph)->ar_hln)) + -+ (((*skb).nh.arph)->ar_pln), sizeof(uint32_t)); -+ if (FWINV(info->daddr != (dst & info->dmsk), -+ EBT_ARP_DST_IP)) -+ return EBT_NOMATCH; -+ } ++ if (info->credit >= info->cost) { ++ /* We're not limited. */ ++ info->credit -= info->cost; ++ spin_unlock_bh(&limit_lock); ++ return EBT_MATCH; + } + -+ if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) -+ { -+ uint32_t arp_len = sizeof(struct arphdr) + -+ (2 * (((*skb).nh.arph)->ar_hln)) + -+ (2 * (((*skb).nh.arph)->ar_pln)); -+ unsigned char dst[ETH_ALEN]; -+ unsigned char src[ETH_ALEN]; -+ -+ // Make sure the packet is long enough. -+ if ((((*skb).nh.raw) + arp_len) > (*skb).tail) -+ return EBT_NOMATCH; -+ // MAC addresses are 6 bytes. -+ if (((*skb).nh.arph)->ar_hln != ETH_ALEN) -+ return EBT_NOMATCH; -+ if (info->bitmask & EBT_ARP_SRC_MAC) { -+ uint8_t verdict, i; -+ -+ memcpy(&src, ((*skb).nh.raw) + -+ sizeof(struct arphdr), -+ ETH_ALEN); -+ verdict = 0; -+ for (i = 0; i < 6; i++) -+ verdict |= (src[i] ^ info->smaddr[i]) & -+ info->smmsk[i]; -+ if (FWINV(verdict != 0, EBT_ARP_SRC_MAC)) -+ return EBT_NOMATCH; -+ } -+ -+ if (info->bitmask & EBT_ARP_DST_MAC) { -+ uint8_t verdict, i; ++ spin_unlock_bh(&limit_lock); ++ return EBT_NOMATCH; ++} + -+ memcpy(&dst, ((*skb).nh.raw) + -+ sizeof(struct arphdr) + -+ (((*skb).nh.arph)->ar_hln) + -+ (((*skb).nh.arph)->ar_pln), -+ ETH_ALEN); -+ verdict = 0; -+ for (i = 0; i < 6; i++) -+ verdict |= (dst[i] ^ info->dmaddr[i]) & -+ info->dmmsk[i]; -+ if (FWINV(verdict != 0, EBT_ARP_DST_MAC)) -+ return EBT_NOMATCH; -+ } -+ } ++/* Precision saver. */ ++static u_int32_t ++user2credits(u_int32_t user) ++{ ++ /* If multiplying would overflow... */ ++ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) ++ /* Divide first. */ ++ return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; + -+ return EBT_MATCH; ++ return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE; +} + -+static int ebt_arp_check(const char *tablename, unsigned int hookmask, ++static int ebt_limit_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) +{ -+ struct ebt_arp_info *info = (struct ebt_arp_info *)data; ++ struct ebt_limit_info *info = (struct ebt_limit_info *)data; + -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info))) -+ return -EINVAL; -+ if ((e->ethproto != __constant_htons(ETH_P_ARP) && -+ e->ethproto != __constant_htons(ETH_P_RARP)) || -+ e->invflags & EBT_IPROTO) ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info))) + return -EINVAL; -+ if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK) ++ ++ /* Check for overflow. */ ++ if (info->burst == 0 ++ || user2credits(info->avg * info->burst) < user2credits(info->avg)) { ++ printk("Overflow in ebt_limit: %u/%u\n", ++ info->avg, info->burst); + return -EINVAL; ++ } ++ ++ /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */ ++ info->prev = jiffies; ++ info->credit = user2credits(info->avg * info->burst); ++ info->credit_cap = user2credits(info->avg * info->burst); ++ info->cost = user2credits(info->avg); + return 0; +} + -+static struct ebt_match filter_arp = ++static struct ebt_match ebt_limit_reg = +{ -+ {NULL, NULL}, EBT_ARP_MATCH, ebt_filter_arp, ebt_arp_check, NULL, ++ {NULL, NULL}, EBT_LIMIT_MATCH, ebt_limit_match, ebt_limit_check, NULL, + THIS_MODULE +}; + +static int __init init(void) +{ -+ return ebt_register_match(&filter_arp); ++ return ebt_register_match(&ebt_limit_reg); +} + +static void __exit fini(void) +{ -+ ebt_unregister_match(&filter_arp); ++ ebt_unregister_match(&ebt_limit_reg); +} + +module_init(init); +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_arpreply.c linux-ebtables/net/bridge/netfilter/ebt_arpreply.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_arpreply.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_arpreply.c 2005-02-07 05:52:50.000000000 +0100 +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_arpreply.c 2005-03-14 00:00:30.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * ebt_arpreply @@ -4047,465 +1173,85 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_arpreply.c linux-ebtables/net/ +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_dnat.c linux-ebtables/net/bridge/netfilter/ebt_dnat.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_dnat.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_dnat.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,65 @@ -+/* -+ * ebt_dnat -+ * -+ * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> -+ * -+ * June, 2002 -+ * -+ */ -+ -+#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_nat.h> -+#include <linux/module.h> -+#include <net/sock.h> -+ -+static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr, -+ const struct net_device *in, const struct net_device *out, -+ const void *data, unsigned int datalen) -+{ -+ struct ebt_nat_info *info = (struct ebt_nat_info *)data; -+ -+ memcpy(((**pskb).mac.ethernet)->h_dest, info->mac, -+ ETH_ALEN * sizeof(unsigned char)); -+ return info->target; -+} -+ -+static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *data, unsigned int datalen) -+{ -+ struct ebt_nat_info *info = (struct ebt_nat_info *)data; -+ -+ if (BASE_CHAIN && info->target == EBT_RETURN) -+ return -EINVAL; -+ CLEAR_BASE_CHAIN_BIT; -+ if ( (strcmp(tablename, "nat") || -+ (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) && -+ (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) -+ return -EINVAL; -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) -+ return -EINVAL; -+ if (INVALID_TARGET) -+ return -EINVAL; -+ return 0; -+} -+ -+static struct ebt_target dnat = -+{ -+ {NULL, NULL}, EBT_DNAT_TARGET, ebt_target_dnat, ebt_target_dnat_check, -+ NULL, THIS_MODULE -+}; -+ -+static int __init init(void) -+{ -+ return ebt_register_target(&dnat); -+} -+ -+static void __exit fini(void) -+{ -+ ebt_unregister_target(&dnat); -+} -+ -+module_init(init); -+module_exit(fini); -+EXPORT_NO_SYMBOLS; -+MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_ip.c linux-ebtables/net/bridge/netfilter/ebt_ip.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_ip.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_ip.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,121 @@ +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_802_3.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,74 @@ +/* -+ * ebt_ip -+ * -+ * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * 802_3 + * -+ * April, 2002 ++ * Author: ++ * Chris Vitale csv@bluetail.com + * -+ * Changes: -+ * added ip-sport and ip-dport -+ * Innominate Security Technologies AG <mhopf@innominate.com> -+ * September, 2002 ++ * May 2003 ++ * + */ + +#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_ip.h> -+#include <linux/ip.h> -+#include <linux/in.h> ++#include <linux/netfilter_bridge/ebt_802_3.h> +#include <linux/module.h> + -+struct tcpudphdr { -+ uint16_t src; -+ uint16_t dst; -+}; -+ -+union h_u { -+ unsigned char *raw; -+ struct tcpudphdr *tuh; -+}; -+ -+static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, -+ const struct net_device *out, const void *data, -+ unsigned int datalen) ++static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, const void *data, unsigned int datalen) +{ -+ struct ebt_ip_info *info = (struct ebt_ip_info *)data; ++ struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; ++ struct ebt_802_3_hdr *hdr = (struct ebt_802_3_hdr *)skb->mac.ethernet; ++ uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; + -+ if (info->bitmask & EBT_IP_TOS && -+ FWINV(info->tos != ((*skb).nh.iph)->tos, EBT_IP_TOS)) -+ return EBT_NOMATCH; -+ if (info->bitmask & EBT_IP_PROTO) { -+ if (FWINV(info->protocol != ((*skb).nh.iph)->protocol, -+ EBT_IP_PROTO)) -+ return EBT_NOMATCH; -+ if ( info->protocol == IPPROTO_TCP || -+ info->protocol == IPPROTO_UDP ) -+ { -+ union h_u h; -+ h.raw = skb->data + skb->nh.iph->ihl*4; -+ if (info->bitmask & EBT_IP_DPORT) { -+ uint16_t port = ntohs(h.tuh->dst); -+ if (FWINV(port < info->dport[0] || -+ port > info->dport[1], -+ EBT_IP_DPORT)) ++ if (info->bitmask & EBT_802_3_SAP) { ++ if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP)) + return EBT_NOMATCH; -+ } -+ if (info->bitmask & EBT_IP_SPORT) { -+ uint16_t port = ntohs(h.tuh->src); -+ if (FWINV(port < info->sport[0] || -+ port > info->sport[1], -+ EBT_IP_SPORT)) ++ if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP)) + return EBT_NOMATCH; -+ } -+ } + } -+ if (info->bitmask & EBT_IP_SOURCE && -+ FWINV((((*skb).nh.iph)->saddr & info->smsk) != -+ info->saddr, EBT_IP_SOURCE)) -+ return EBT_NOMATCH; -+ if ((info->bitmask & EBT_IP_DEST) && -+ FWINV((((*skb).nh.iph)->daddr & info->dmsk) != -+ info->daddr, EBT_IP_DEST)) -+ return EBT_NOMATCH; -+ return EBT_MATCH; -+} -+ -+static int ebt_ip_check(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *data, unsigned int datalen) -+{ -+ struct ebt_ip_info *info = (struct ebt_ip_info *)data; -+ -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info))) -+ return -EINVAL; -+ if (e->ethproto != __constant_htons(ETH_P_IP) || -+ e->invflags & EBT_IPROTO) -+ return -EINVAL; -+ if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) -+ return -EINVAL; -+ if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { -+ if (!info->bitmask & EBT_IPROTO) -+ return -EINVAL; -+ if (info->protocol != IPPROTO_TCP && -+ info->protocol != IPPROTO_UDP) -+ return -EINVAL; -+ } -+ if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) -+ return -EINVAL; -+ if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) -+ return -EINVAL; -+ return 0; -+} -+ -+static struct ebt_match filter_ip = -+{ -+ {NULL, NULL}, EBT_IP_MATCH, ebt_filter_ip, ebt_ip_check, NULL, -+ THIS_MODULE -+}; -+ -+static int __init init(void) -+{ -+ return ebt_register_match(&filter_ip); -+} -+ -+static void __exit fini(void) -+{ -+ ebt_unregister_match(&filter_ip); -+} -+ -+module_init(init); -+module_exit(fini); -+EXPORT_NO_SYMBOLS; -+MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_limit.c linux-ebtables/net/bridge/netfilter/ebt_limit.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_limit.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_limit.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,101 @@ -+/* -+ * ebt_limit -+ * -+ * Authors: -+ * Tom Marshall <tommy@home.tig-grr.com> -+ * -+ * Mostly copied from netfilter's ipt_limit.c, see that file for explanation -+ * -+ * September, 2003 -+ * -+ */ -+ -+#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_limit.h> -+#include <linux/module.h> -+ -+#include <linux/netdevice.h> -+#include <linux/spinlock.h> -+ -+static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED; -+ -+#define CREDITS_PER_JIFFY 128 -+ -+static int ebt_limit_match(const struct sk_buff *skb, const struct net_device *in, -+ const struct net_device *out, const void *data, unsigned int datalen) -+{ -+ struct ebt_limit_info *info = (struct ebt_limit_info *)data; -+ unsigned long now = jiffies; -+ -+ spin_lock_bh(&limit_lock); -+ info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY; -+ if (info->credit > info->credit_cap) -+ info->credit = info->credit_cap; + -+ if (info->credit >= info->cost) { -+ /* We're not limited. */ -+ info->credit -= info->cost; -+ spin_unlock_bh(&limit_lock); -+ return EBT_MATCH; ++ if (info->bitmask & EBT_802_3_TYPE) { ++ if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE)) ++ return EBT_NOMATCH; ++ if (FWINV(info->type != type, EBT_802_3_TYPE)) ++ return EBT_NOMATCH; + } + -+ spin_unlock_bh(&limit_lock); -+ return EBT_NOMATCH; -+} -+ -+/* Precision saver. */ -+static u_int32_t -+user2credits(u_int32_t user) -+{ -+ /* If multiplying would overflow... */ -+ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) -+ /* Divide first. */ -+ return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; -+ -+ return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE; ++ return EBT_MATCH; +} + -+static int ebt_limit_check(const char *tablename, unsigned int hookmask, ++static struct ebt_match filter_802_3; ++static int ebt_802_3_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) +{ -+ struct ebt_limit_info *info = (struct ebt_limit_info *)data; ++ struct ebt_802_3_info *info = (struct ebt_802_3_info *)data; + -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info))) ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_802_3_info))) + return -EINVAL; -+ -+ /* Check for overflow. */ -+ if (info->burst == 0 -+ || user2credits(info->avg * info->burst) < user2credits(info->avg)) { -+ printk("Overflow in ebt_limit: %u/%u\n", -+ info->avg, info->burst); ++ if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK) + return -EINVAL; -+ } -+ -+ /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */ -+ info->prev = jiffies; -+ info->credit = user2credits(info->avg * info->burst); -+ info->credit_cap = user2credits(info->avg * info->burst); -+ info->cost = user2credits(info->avg); -+ return 0; -+} -+ -+static struct ebt_match ebt_limit_reg = -+{ -+ {NULL, NULL}, EBT_LIMIT_MATCH, ebt_limit_match, ebt_limit_check, NULL, -+ THIS_MODULE -+}; -+ -+static int __init init(void) -+{ -+ return ebt_register_match(&ebt_limit_reg); -+} -+ -+static void __exit fini(void) -+{ -+ ebt_unregister_match(&ebt_limit_reg); -+} -+ -+module_init(init); -+module_exit(fini); -+EXPORT_NO_SYMBOLS; -+MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_log.c linux-ebtables/net/bridge/netfilter/ebt_log.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_log.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_log.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,153 @@ -+/* -+ * ebt_log -+ * -+ * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> -+ * -+ * April, 2002 -+ * -+ */ -+ -+#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_log.h> -+#include <linux/module.h> -+#include <linux/ip.h> -+#include <linux/in.h> -+#include <linux/if_arp.h> -+#include <linux/spinlock.h> -+ -+static spinlock_t ebt_log_lock = SPIN_LOCK_UNLOCKED; -+ -+static int ebt_log_check(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *data, unsigned int datalen) -+{ -+ struct ebt_log_info *info = (struct ebt_log_info *)data; + -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_log_info))) -+ return -EINVAL; -+ if (info->bitmask & ~EBT_LOG_MASK) -+ return -EINVAL; -+ if (info->loglevel >= 8) -+ return -EINVAL; -+ info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; + return 0; +} + -+struct tcpudphdr -+{ -+ uint16_t src; -+ uint16_t dst; -+}; -+ -+struct arppayload -+{ -+ unsigned char mac_src[ETH_ALEN]; -+ unsigned char ip_src[4]; -+ unsigned char mac_dst[ETH_ALEN]; -+ unsigned char ip_dst[4]; -+}; -+ -+static void print_MAC(unsigned char *p) -+{ -+ int i; -+ -+ for (i = 0; i < ETH_ALEN; i++, p++) -+ printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':'); -+} -+ -+#define myNIPQUAD(a) a[0], a[1], a[2], a[3] -+static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, -+ const struct net_device *in, const struct net_device *out, -+ const void *data, unsigned int datalen) -+{ -+ struct ebt_log_info *info = (struct ebt_log_info *)data; -+ char level_string[4] = "< >"; -+ level_string[1] = '0' + info->loglevel; -+ -+ spin_lock_bh(&ebt_log_lock); -+ printk(level_string); -+ printk("%s IN=%s OUT=%s ", info->prefix, in ? in->name : "", -+ out ? out->name : ""); -+ -+ printk("MAC source = "); -+ print_MAC((skb->mac.ethernet)->h_source); -+ printk("MAC dest = "); -+ print_MAC((skb->mac.ethernet)->h_dest); -+ -+ printk("proto = 0x%04x", ntohs(((*skb).mac.ethernet)->h_proto)); -+ -+ if ((info->bitmask & EBT_LOG_IP) && skb->mac.ethernet->h_proto == -+ htons(ETH_P_IP)){ -+ struct iphdr *iph = skb->nh.iph; -+ printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,", -+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); -+ printk(" IP tos=0x%02X, IP proto=%d", iph->tos, iph->protocol); -+ if (iph->protocol == IPPROTO_TCP || -+ iph->protocol == IPPROTO_UDP) { -+ struct tcpudphdr *ports = (struct tcpudphdr *)(skb->data + iph->ihl*4); -+ -+ if (skb->data + iph->ihl*4 > skb->tail) { -+ printk(" INCOMPLETE TCP/UDP header"); -+ goto out; -+ } -+ printk(" SPT=%u DPT=%u", ntohs(ports->src), -+ ntohs(ports->dst)); -+ } -+ goto out; -+ } -+ -+ if ((info->bitmask & EBT_LOG_ARP) && -+ ((skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) || -+ (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_RARP)))) { -+ struct arphdr * arph = skb->nh.arph; -+ printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d", -+ ntohs(arph->ar_hrd), ntohs(arph->ar_pro), -+ ntohs(arph->ar_op)); -+ /* If it's for Ethernet and the lengths are OK, -+ * then log the ARP payload */ -+ if (arph->ar_hrd == __constant_htons(1) && -+ arph->ar_hln == ETH_ALEN && -+ arph->ar_pln == sizeof(uint32_t)) { -+ struct arppayload *arpp = (struct arppayload *)(skb->data + sizeof(*arph)); -+ -+ if (skb->data + sizeof(*arph) > skb->tail) { -+ printk(" INCOMPLETE ARP header"); -+ goto out; -+ } -+ -+ printk(" ARP MAC SRC="); -+ print_MAC(arpp->mac_src); -+ printk(" ARP IP SRC=%u.%u.%u.%u", -+ myNIPQUAD(arpp->ip_src)); -+ printk(" ARP MAC DST="); -+ print_MAC(arpp->mac_dst); -+ printk(" ARP IP DST=%u.%u.%u.%u", -+ myNIPQUAD(arpp->ip_dst)); -+ } -+ -+ } -+out: -+ printk("\n"); -+ spin_unlock_bh(&ebt_log_lock); -+} -+ -+static struct ebt_watcher log = ++static struct ebt_match filter_802_3 = +{ -+ {NULL, NULL}, EBT_LOG_WATCHER, ebt_log, ebt_log_check, NULL, -+ THIS_MODULE ++ .name = EBT_802_3_MATCH, ++ .match = ebt_filter_802_3, ++ .check = ebt_802_3_check, ++ .me = THIS_MODULE, +}; + +static int __init init(void) +{ -+ return ebt_register_watcher(&log); ++ return ebt_register_match(&filter_802_3); +} + +static void __exit fini(void) +{ -+ ebt_unregister_watcher(&log); ++ ebt_unregister_match(&filter_802_3); +} + +module_init(init); +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_mark.c linux-ebtables/net/bridge/netfilter/ebt_mark.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_mark.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_mark.c 2005-02-07 05:52:50.000000000 +0100 +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_mark.c 2005-03-14 00:00:30.000000000 +0100 @@ -0,0 +1,66 @@ +/* + * ebt_mark @@ -4573,9 +1319,8 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_mark.c linux-ebtables/net/brid +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_mark_m.c linux-ebtables/net/bridge/netfilter/ebt_mark_m.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_mark_m.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_mark_m.c 2005-02-07 05:52:50.000000000 +0100 +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_mark_m.c 2005-03-14 00:00:30.000000000 +0100 @@ -0,0 +1,61 @@ +/* + * ebt_mark_m @@ -4638,9 +1383,8 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_mark_m.c linux-ebtables/net/br +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_pkttype.c linux-ebtables/net/bridge/netfilter/ebt_pkttype.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_pkttype.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_pkttype.c 2005-02-07 05:52:50.000000000 +0100 +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_pkttype.c 2005-03-14 00:00:30.000000000 +0100 @@ -0,0 +1,60 @@ +/* + * ebt_pkttype @@ -4702,152 +1446,8 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_pkttype.c linux-ebtables/net/b +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_redirect.c linux-ebtables/net/bridge/netfilter/ebt_redirect.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_redirect.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_redirect.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,71 @@ -+/* -+ * ebt_redirect -+ * -+ * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> -+ * -+ * April, 2002 -+ * -+ */ -+ -+#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_redirect.h> -+#include <linux/module.h> -+#include <net/sock.h> -+#include "../br_private.h" -+ -+static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr, -+ const struct net_device *in, const struct net_device *out, -+ const void *data, unsigned int datalen) -+{ -+ struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; -+ -+ if (hooknr != NF_BR_BROUTING) -+ memcpy((**pskb).mac.ethernet->h_dest, -+ in->br_port->br->dev.dev_addr, ETH_ALEN); -+ else { -+ memcpy((**pskb).mac.ethernet->h_dest, -+ in->dev_addr, ETH_ALEN); -+ (*pskb)->pkt_type = PACKET_HOST; -+ } -+ return info->target; -+} -+ -+static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *data, unsigned int datalen) -+{ -+ struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; -+ -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_redirect_info))) -+ return -EINVAL; -+ if (BASE_CHAIN && info->target == EBT_RETURN) -+ return -EINVAL; -+ CLEAR_BASE_CHAIN_BIT; -+ if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) && -+ (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) -+ return -EINVAL; -+ if (INVALID_TARGET) -+ return -EINVAL; -+ return 0; -+} -+ -+static struct ebt_target redirect_target = -+{ -+ {NULL, NULL}, EBT_REDIRECT_TARGET, ebt_target_redirect, -+ ebt_target_redirect_check, NULL, THIS_MODULE -+}; -+ -+static int __init init(void) -+{ -+ return ebt_register_target(&redirect_target); -+} -+ -+static void __exit fini(void) -+{ -+ ebt_unregister_target(&redirect_target); -+} -+ -+module_init(init); -+module_exit(fini); -+EXPORT_NO_SYMBOLS; -+MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_snat.c linux-ebtables/net/bridge/netfilter/ebt_snat.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_snat.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_snat.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,64 @@ -+/* -+ * ebt_snat -+ * -+ * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> -+ * -+ * June, 2002 -+ * -+ */ -+ -+#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_nat.h> -+#include <linux/module.h> -+ -+static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, -+ const struct net_device *in, const struct net_device *out, -+ const void *data, unsigned int datalen) -+{ -+ struct ebt_nat_info *info = (struct ebt_nat_info *) data; -+ -+ memcpy(((**pskb).mac.ethernet)->h_source, info->mac, -+ ETH_ALEN * sizeof(unsigned char)); -+ return info->target; -+} -+ -+static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, -+ const struct ebt_entry *e, void *data, unsigned int datalen) -+{ -+ struct ebt_nat_info *info = (struct ebt_nat_info *) data; -+ -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) -+ return -EINVAL; -+ if (BASE_CHAIN && info->target == EBT_RETURN) -+ return -EINVAL; -+ CLEAR_BASE_CHAIN_BIT; -+ if (strcmp(tablename, "nat")) -+ return -EINVAL; -+ if (hookmask & ~(1 << NF_BR_POST_ROUTING)) -+ return -EINVAL; -+ if (INVALID_TARGET) -+ return -EINVAL; -+ return 0; -+} -+ -+static struct ebt_target snat = -+{ -+ {NULL, NULL}, EBT_SNAT_TARGET, ebt_target_snat, ebt_target_snat_check, -+ NULL, THIS_MODULE -+}; -+ -+static int __init init(void) -+{ -+ return ebt_register_target(&snat); -+} -+ -+static void __exit fini(void) -+{ -+ ebt_unregister_target(&snat); -+} -+ -+module_init(init); -+module_exit(fini); -+EXPORT_NO_SYMBOLS; -+MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_stp.c linux-ebtables/net/bridge/netfilter/ebt_stp.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_stp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_stp.c 2005-02-07 05:52:50.000000000 +0100 +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_stp.c 2005-03-14 00:00:30.000000000 +0100 @@ -0,0 +1,191 @@ +/* + * ebt_stp @@ -5040,294 +1640,358 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_stp.c linux-ebtables/net/bridg +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_ulog.c linux-ebtables/net/bridge/netfilter/ebt_ulog.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_ulog.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_ulog.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,281 @@ +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_redirect.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,71 @@ +/* -+ * netfilter module for userspace bridged Ethernet frames logging daemons ++ * ebt_redirect + * + * Authors: -+ * Bart De Schuymer <bdschuym@pandora.be> -+ * -+ * November, 2004 -+ * -+ * Based on ipt_ULOG.c, which is -+ * (C) 2000-2002 by Harald Welte <laforge@netfilter.org> -+ * -+ * This module accepts two parameters: -+ * -+ * nlbufsiz: -+ * The parameter specifies how big the buffer for each netlink multicast -+ * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will -+ * get accumulated in the kernel until they are sent to userspace. It is -+ * NOT possible to allocate more than 128kB, and it is strongly discouraged, -+ * because atomically allocating 128kB inside the network rx softirq is not -+ * reliable. Please also keep in mind that this buffer size is allocated for -+ * each nlgroup you are using, so the total kernel memory usage increases -+ * by that factor. ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> + * -+ * flushtimeout: -+ * Specify, after how many hundredths of a second the queue should be -+ * flushed even if it is not full yet. ++ * April, 2002 + * + */ + -+#include <linux/module.h> -+#include <linux/config.h> -+#include <linux/spinlock.h> -+#include <linux/socket.h> -+#include <linux/skbuff.h> -+#include <linux/kernel.h> -+#include <linux/timer.h> -+#include <linux/netlink.h> -+#include <linux/netdevice.h> -+#include <linux/module.h> +#include <linux/netfilter_bridge/ebtables.h> -+#include <linux/netfilter_bridge/ebt_ulog.h> ++#include <linux/netfilter_bridge/ebt_redirect.h> ++#include <linux/module.h> +#include <net/sock.h> +#include "../br_private.h" + -+#define PRINTR(format, args...) do { if (net_ratelimit()) \ -+ printk(format , ## args); } while (0) -+ -+static unsigned int nlbufsiz = 4096; -+MODULE_PARM(nlbufsiz, "i"); -+MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " -+ "(defaults to 4096)"); -+ -+static unsigned int flushtimeout = 10; -+MODULE_PARM(flushtimeout, "i"); -+MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second) " -+ "(defaults to 10)"); -+ -+typedef struct { -+ unsigned int qlen; /* number of nlmsgs' in the skb */ -+ struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ -+ struct sk_buff *skb; /* the pre-allocated skb */ -+ struct timer_list timer; /* the timer function */ -+ spinlock_t lock; /* the per-queue lock */ -+} ebt_ulog_buff_t; -+ -+static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; -+static struct sock *ebtlognl; -+ -+/* send one ulog_buff_t to userspace */ -+static void ulog_send(unsigned int nlgroup) ++static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *data, unsigned int datalen) +{ -+ ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup]; -+ -+ if (timer_pending(&ub->timer)) -+ del_timer(&ub->timer); -+ -+ /* last nlmsg needs NLMSG_DONE */ -+ if (ub->qlen > 1) -+ ub->lastnlh->nlmsg_type = NLMSG_DONE; -+ -+ NETLINK_CB(ub->skb).dst_groups = 1 << nlgroup; -+ netlink_broadcast(ebtlognl, ub->skb, 0, 1 << nlgroup, GFP_ATOMIC); ++ struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; + -+ ub->qlen = 0; -+ ub->skb = NULL; ++ if (hooknr != NF_BR_BROUTING) ++ memcpy((**pskb).mac.ethernet->h_dest, ++ in->br_port->br->dev.dev_addr, ETH_ALEN); ++ else { ++ memcpy((**pskb).mac.ethernet->h_dest, ++ in->dev_addr, ETH_ALEN); ++ (*pskb)->pkt_type = PACKET_HOST; ++ } ++ return info->target; +} + -+/* timer function to flush queue in flushtimeout time */ -+static void ulog_timer(unsigned long data) ++static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) +{ -+ spin_lock_bh(&ulog_buffers[data].lock); -+ if (ulog_buffers[data].skb) -+ ulog_send(data); -+ spin_unlock_bh(&ulog_buffers[data].lock); ++ struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; ++ ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_redirect_info))) ++ return -EINVAL; ++ if (BASE_CHAIN && info->target == EBT_RETURN) ++ return -EINVAL; ++ CLEAR_BASE_CHAIN_BIT; ++ if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) && ++ (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) ++ return -EINVAL; ++ if (INVALID_TARGET) ++ return -EINVAL; ++ return 0; +} + -+static struct sk_buff *ulog_alloc_skb(unsigned int size) ++static struct ebt_target redirect_target = +{ -+ struct sk_buff *skb; -+ -+ skb = alloc_skb(nlbufsiz, GFP_ATOMIC); -+ if (!skb) { -+ PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " -+ "of size %ub!\n", nlbufsiz); -+ if (size < nlbufsiz) { -+ /* try to allocate only as much as we need for -+ * current packet */ -+ skb = alloc_skb(size, GFP_ATOMIC); -+ if (!skb) -+ PRINTR(KERN_ERR "ebt_ulog: can't even allocate " -+ "buffer of size %ub\n", size); -+ } -+ } ++ {NULL, NULL}, EBT_REDIRECT_TARGET, ebt_target_redirect, ++ ebt_target_redirect_check, NULL, THIS_MODULE ++}; + -+ return skb; ++static int __init init(void) ++{ ++ return ebt_register_target(&redirect_target); +} + -+static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, -+ const struct net_device *in, const struct net_device *out, -+ const void *data, unsigned int datalen) ++static void __exit fini(void) +{ -+ ebt_ulog_packet_msg_t *pm; -+ size_t size, copy_len; -+ struct nlmsghdr *nlh; -+ struct ebt_ulog_info *loginfo = (struct ebt_ulog_info *)data; -+ unsigned int group = loginfo->nlgroup; -+ ebt_ulog_buff_t *ub = &ulog_buffers[group]; -+ spinlock_t *lock = &ub->lock; -+ -+ if ((loginfo->cprange == 0) || -+ (loginfo->cprange > skb->len + ETH_HLEN)) -+ copy_len = skb->len + ETH_HLEN; -+ else -+ copy_len = loginfo->cprange; ++ ebt_unregister_target(&redirect_target); ++} + -+ size = NLMSG_SPACE(sizeof(*pm) + copy_len); ++module_init(init); ++module_exit(fini); ++EXPORT_NO_SYMBOLS; ++MODULE_LICENSE("GPL"); +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_arp.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,149 @@ ++/* ++ * ebt_arp ++ * ++ * Authors: ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * Tim Gardner <timg@tpi.com> ++ * ++ * April, 2002 ++ * ++ */ + -+ spin_lock_bh(lock); ++#include <linux/netfilter_bridge/ebtables.h> ++#include <linux/netfilter_bridge/ebt_arp.h> ++#include <linux/if_arp.h> ++#include <linux/if_ether.h> ++#include <linux/module.h> + -+ if (!ub->skb) { -+ if (!(ub->skb = ulog_alloc_skb(size))) -+ goto alloc_failure; -+ } else if (size > skb_tailroom(ub->skb)) { -+ ulog_send(group); ++static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, const void *data, unsigned int datalen) ++{ ++ struct ebt_arp_info *info = (struct ebt_arp_info *)data; + -+ if (!(ub->skb = ulog_alloc_skb(size))) -+ goto alloc_failure; -+ } ++ if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode != ++ ((*skb).nh.arph)->ar_op, EBT_ARP_OPCODE)) ++ return EBT_NOMATCH; ++ if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype != ++ ((*skb).nh.arph)->ar_hrd, EBT_ARP_HTYPE)) ++ return EBT_NOMATCH; ++ if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype != ++ ((*skb).nh.arph)->ar_pro, EBT_ARP_PTYPE)) ++ return EBT_NOMATCH; + -+ nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0, -+ size - NLMSG_ALIGN(sizeof(*nlh))); -+ ub->qlen++; ++ if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) ++ { ++ uint32_t arp_len = sizeof(struct arphdr) + ++ (2 * (((*skb).nh.arph)->ar_hln)) + ++ (2 * (((*skb).nh.arph)->ar_pln)); ++ uint32_t dst; ++ uint32_t src; + -+ pm = NLMSG_DATA(nlh); ++ // Make sure the packet is long enough. ++ if ((((*skb).nh.raw) + arp_len) > (*skb).tail) ++ return EBT_NOMATCH; ++ // IPv4 addresses are always 4 bytes. ++ if (((*skb).nh.arph)->ar_pln != sizeof(uint32_t)) ++ return EBT_NOMATCH; + -+ /* Fill in the ulog data */ -+ do_gettimeofday(&pm->stamp); -+ if (ub->qlen == 1) -+ ub->skb->stamp = pm->stamp; -+ pm->data_len = copy_len; -+ pm->mark = skb->nfmark; -+ pm->hook = hooknr; -+ if (loginfo->prefix != NULL) -+ strcpy(pm->prefix, loginfo->prefix); -+ else -+ *(pm->prefix) = '\0'; ++ if (info->bitmask & EBT_ARP_SRC_IP) { ++ memcpy(&src, ((*skb).nh.raw) + sizeof(struct arphdr) + ++ ((*skb).nh.arph)->ar_hln, sizeof(uint32_t)); ++ if (FWINV(info->saddr != (src & info->smsk), ++ EBT_ARP_SRC_IP)) ++ return EBT_NOMATCH; ++ } + -+ if (in) { -+ strcpy(pm->physindev, in->name); -+ strcpy(pm->indev, in->br_port->br->dev.name); -+ } else -+ pm->indev[0] = pm->physindev[0] = '\0'; ++ if (info->bitmask & EBT_ARP_DST_IP) { ++ memcpy(&dst, ((*skb).nh.raw)+sizeof(struct arphdr) + ++ (2*(((*skb).nh.arph)->ar_hln)) + ++ (((*skb).nh.arph)->ar_pln), sizeof(uint32_t)); ++ if (FWINV(info->daddr != (dst & info->dmsk), ++ EBT_ARP_DST_IP)) ++ return EBT_NOMATCH; ++ } ++ } + -+ if (out) { -+ strcpy(pm->physoutdev, out->name); -+ strcpy(pm->outdev, out->br_port->br->dev.name); -+ } else -+ pm->outdev[0] = pm->physoutdev[0] = '\0'; ++ if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) ++ { ++ uint32_t arp_len = sizeof(struct arphdr) + ++ (2 * (((*skb).nh.arph)->ar_hln)) + ++ (2 * (((*skb).nh.arph)->ar_pln)); ++ unsigned char dst[ETH_ALEN]; ++ unsigned char src[ETH_ALEN]; + -+ if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) -+ BUG(); ++ // Make sure the packet is long enough. ++ if ((((*skb).nh.raw) + arp_len) > (*skb).tail) ++ return EBT_NOMATCH; ++ // MAC addresses are 6 bytes. ++ if (((*skb).nh.arph)->ar_hln != ETH_ALEN) ++ return EBT_NOMATCH; ++ if (info->bitmask & EBT_ARP_SRC_MAC) { ++ uint8_t verdict, i; + -+ if (ub->qlen > 1) -+ ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; ++ memcpy(&src, ((*skb).nh.raw) + ++ sizeof(struct arphdr), ++ ETH_ALEN); ++ verdict = 0; ++ for (i = 0; i < 6; i++) ++ verdict |= (src[i] ^ info->smaddr[i]) & ++ info->smmsk[i]; ++ if (FWINV(verdict != 0, EBT_ARP_SRC_MAC)) ++ return EBT_NOMATCH; ++ } + -+ ub->lastnlh = nlh; ++ if (info->bitmask & EBT_ARP_DST_MAC) { ++ uint8_t verdict, i; + -+ if (ub->qlen >= loginfo->qthreshold) -+ ulog_send(group); -+ else if (!timer_pending(&ub->timer)) { -+ ub->timer.expires = jiffies + flushtimeout * HZ / 100; -+ add_timer(&ub->timer); ++ memcpy(&dst, ((*skb).nh.raw) + ++ sizeof(struct arphdr) + ++ (((*skb).nh.arph)->ar_hln) + ++ (((*skb).nh.arph)->ar_pln), ++ ETH_ALEN); ++ verdict = 0; ++ for (i = 0; i < 6; i++) ++ verdict |= (dst[i] ^ info->dmaddr[i]) & ++ info->dmmsk[i]; ++ if (FWINV(verdict != 0, EBT_ARP_DST_MAC)) ++ return EBT_NOMATCH; ++ } + } + -+unlock: -+ spin_unlock_bh(lock); -+ -+ return; -+ -+nlmsg_failure: -+ PRINTR(KERN_ERR "ebt_ULOG: error during NLMSG_PUT.\n"); -+ goto unlock; -+alloc_failure: -+ goto unlock; ++ return EBT_MATCH; +} + -+static int ebt_ulog_check(const char *tablename, unsigned int hookmask, ++static int ebt_arp_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) +{ -+ struct ebt_ulog_info *loginfo = (struct ebt_ulog_info *)data; ++ struct ebt_arp_info *info = (struct ebt_arp_info *)data; + -+ if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) || -+ loginfo->nlgroup > 31) ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info))) ++ return -EINVAL; ++ if ((e->ethproto != __constant_htons(ETH_P_ARP) && ++ e->ethproto != __constant_htons(ETH_P_RARP)) || ++ e->invflags & EBT_IPROTO) ++ return -EINVAL; ++ if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK) + return -EINVAL; -+ -+ loginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; -+ -+ if (loginfo->qthreshold > EBT_ULOG_MAX_QLEN) -+ loginfo->qthreshold = EBT_ULOG_MAX_QLEN; -+ + return 0; +} + -+static struct ebt_watcher ulog = { -+ {NULL, NULL}, EBT_ULOG_WATCHER, ebt_ulog, ebt_ulog_check, NULL, ++static struct ebt_match filter_arp = ++{ ++ {NULL, NULL}, EBT_ARP_MATCH, ebt_filter_arp, ebt_arp_check, NULL, + THIS_MODULE +}; + +static int __init init(void) +{ -+ int i, ret = 0; ++ return ebt_register_match(&filter_arp); ++} + -+ if (nlbufsiz >= 128*1024) { -+ printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB," -+ " please try a smaller nlbufsiz parameter.\n"); -+ return -EINVAL; ++static void __exit fini(void) ++{ ++ ebt_unregister_match(&filter_arp); ++} ++ ++module_init(init); ++module_exit(fini); ++EXPORT_NO_SYMBOLS; ++MODULE_LICENSE("GPL"); +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_ip.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,121 @@ ++/* ++ * ebt_ip ++ * ++ * Authors: ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * ++ * April, 2002 ++ * ++ * Changes: ++ * added ip-sport and ip-dport ++ * Innominate Security Technologies AG <mhopf@innominate.com> ++ * September, 2002 ++ */ ++ ++#include <linux/netfilter_bridge/ebtables.h> ++#include <linux/netfilter_bridge/ebt_ip.h> ++#include <linux/ip.h> ++#include <linux/in.h> ++#include <linux/module.h> ++ ++struct tcpudphdr { ++ uint16_t src; ++ uint16_t dst; ++}; ++ ++union h_u { ++ unsigned char *raw; ++ struct tcpudphdr *tuh; ++}; ++ ++static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, const void *data, ++ unsigned int datalen) ++{ ++ struct ebt_ip_info *info = (struct ebt_ip_info *)data; ++ ++ if (info->bitmask & EBT_IP_TOS && ++ FWINV(info->tos != ((*skb).nh.iph)->tos, EBT_IP_TOS)) ++ return EBT_NOMATCH; ++ if (info->bitmask & EBT_IP_PROTO) { ++ if (FWINV(info->protocol != ((*skb).nh.iph)->protocol, ++ EBT_IP_PROTO)) ++ return EBT_NOMATCH; ++ if ( info->protocol == IPPROTO_TCP || ++ info->protocol == IPPROTO_UDP ) ++ { ++ union h_u h; ++ h.raw = skb->data + skb->nh.iph->ihl*4; ++ if (info->bitmask & EBT_IP_DPORT) { ++ uint16_t port = ntohs(h.tuh->dst); ++ if (FWINV(port < info->dport[0] || ++ port > info->dport[1], ++ EBT_IP_DPORT)) ++ return EBT_NOMATCH; ++ } ++ if (info->bitmask & EBT_IP_SPORT) { ++ uint16_t port = ntohs(h.tuh->src); ++ if (FWINV(port < info->sport[0] || ++ port > info->sport[1], ++ EBT_IP_SPORT)) ++ return EBT_NOMATCH; ++ } ++ } + } ++ if (info->bitmask & EBT_IP_SOURCE && ++ FWINV((((*skb).nh.iph)->saddr & info->smsk) != ++ info->saddr, EBT_IP_SOURCE)) ++ return EBT_NOMATCH; ++ if ((info->bitmask & EBT_IP_DEST) && ++ FWINV((((*skb).nh.iph)->daddr & info->dmsk) != ++ info->daddr, EBT_IP_DEST)) ++ return EBT_NOMATCH; ++ return EBT_MATCH; ++} + -+ /* initialize ulog_buffers */ -+ for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { -+ init_timer(&ulog_buffers[i].timer); -+ ulog_buffers[i].timer.function = ulog_timer; -+ ulog_buffers[i].timer.data = i; -+ ulog_buffers[i].lock = SPIN_LOCK_UNLOCKED; ++static int ebt_ip_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) ++{ ++ struct ebt_ip_info *info = (struct ebt_ip_info *)data; ++ ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info))) ++ return -EINVAL; ++ if (e->ethproto != __constant_htons(ETH_P_IP) || ++ e->invflags & EBT_IPROTO) ++ return -EINVAL; ++ if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) ++ return -EINVAL; ++ if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { ++ if (!info->bitmask & EBT_IPROTO) ++ return -EINVAL; ++ if (info->protocol != IPPROTO_TCP && ++ info->protocol != IPPROTO_UDP) ++ return -EINVAL; + } ++ if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) ++ return -EINVAL; ++ if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) ++ return -EINVAL; ++ return 0; ++} + -+ ebtlognl = netlink_kernel_create(NETLINK_NFLOG, NULL); -+ if (!ebtlognl) -+ ret = -ENOMEM; -+ else if ((ret = ebt_register_watcher(&ulog))) -+ sock_release(ebtlognl->socket); ++static struct ebt_match filter_ip = ++{ ++ {NULL, NULL}, EBT_IP_MATCH, ebt_filter_ip, ebt_ip_check, NULL, ++ THIS_MODULE ++}; + -+ return ret; ++static int __init init(void) ++{ ++ return ebt_register_match(&filter_ip); +} + +static void __exit fini(void) +{ -+ ebt_ulog_buff_t *ub; -+ int i; -+ -+ ebt_unregister_watcher(&ulog); -+ for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { -+ ub = &ulog_buffers[i]; -+ if (timer_pending(&ub->timer)) -+ del_timer(&ub->timer); -+ spin_lock_bh(&ub->lock); -+ if (ub->skb) { -+ kfree_skb(ub->skb); -+ ub->skb = NULL; -+ } -+ spin_unlock_bh(&ub->lock); -+ } -+ sock_release(ebtlognl->socket); ++ ebt_unregister_match(&filter_ip); +} + +module_init(init); +module_exit(fini); ++EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); -+MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet" -+ " frames"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_vlan.c linux-ebtables/net/bridge/netfilter/ebt_vlan.c ---- linux-mips-cvs/net/bridge/netfilter/ebt_vlan.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebt_vlan.c 2005-02-07 05:52:50.000000000 +0100 +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_vlan.c 2005-03-14 00:00:30.000000000 +0100 @@ -0,0 +1,259 @@ +/* + * Description: EBTables 802.1Q match extension kernelspace module. @@ -5588,287 +2252,584 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebt_vlan.c linux-ebtables/net/brid +module_exit(fini); + +EXPORT_NO_SYMBOLS; -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebtable_broute.c linux-ebtables/net/bridge/netfilter/ebtable_broute.c ---- linux-mips-cvs/net/bridge/netfilter/ebtable_broute.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebtable_broute.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,79 @@ +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_log.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,153 @@ +/* -+ * ebtable_broute ++ * ebt_log + * + * Authors: + * Bart De Schuymer <bart.de.schuymer@pandora.be> + * + * April, 2002 + * -+ * This table lets you choose between routing and bridging for frames -+ * entering on a bridge enslaved nic. This table is traversed before any -+ * other ebtables table. See net/bridge/br_input.c. + */ + +#include <linux/netfilter_bridge/ebtables.h> ++#include <linux/netfilter_bridge/ebt_log.h> +#include <linux/module.h> -+#include <linux/if_bridge.h> -+#include <linux/brlock.h> ++#include <linux/ip.h> ++#include <linux/in.h> ++#include <linux/if_arp.h> ++#include <linux/spinlock.h> + -+// EBT_ACCEPT means the frame will be bridged -+// EBT_DROP means the frame will be routed -+static struct ebt_entries initial_chain = -+ {0, "BROUTING", 0, EBT_ACCEPT, 0}; ++static spinlock_t ebt_log_lock = SPIN_LOCK_UNLOCKED; + -+static struct ebt_replace initial_table = ++static int ebt_log_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) +{ -+ "broute", 1 << NF_BR_BROUTING, 0, sizeof(struct ebt_entries), -+ { [NF_BR_BROUTING]&initial_chain}, 0, NULL, (char *)&initial_chain -+}; ++ struct ebt_log_info *info = (struct ebt_log_info *)data; + -+static int check(const struct ebt_table_info *info, unsigned int valid_hooks) -+{ -+ if (valid_hooks & ~(1 << NF_BR_BROUTING)) ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_log_info))) ++ return -EINVAL; ++ if (info->bitmask & ~EBT_LOG_MASK) + return -EINVAL; ++ if (info->loglevel >= 8) ++ return -EINVAL; ++ info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; + return 0; +} + -+static struct ebt_table broute_table = ++struct tcpudphdr +{ -+ {NULL, NULL}, "broute", &initial_table, 1 << NF_BR_BROUTING, -+ RW_LOCK_UNLOCKED, check, NULL ++ uint16_t src; ++ uint16_t dst; +}; + -+static int ebt_broute(struct sk_buff **pskb) ++struct arppayload +{ -+ int ret; ++ unsigned char mac_src[ETH_ALEN]; ++ unsigned char ip_src[4]; ++ unsigned char mac_dst[ETH_ALEN]; ++ unsigned char ip_dst[4]; ++}; + -+ ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL, -+ &broute_table); -+ if (ret == NF_DROP) -+ return 1; // route it -+ return 0; // bridge it ++static void print_MAC(unsigned char *p) ++{ ++ int i; ++ ++ for (i = 0; i < ETH_ALEN; i++, p++) ++ printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':'); +} + -+static int __init init(void) ++#define myNIPQUAD(a) a[0], a[1], a[2], a[3] ++static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *data, unsigned int datalen) +{ -+ int ret; ++ struct ebt_log_info *info = (struct ebt_log_info *)data; ++ char level_string[4] = "< >"; ++ level_string[1] = '0' + info->loglevel; + -+ ret = ebt_register_table(&broute_table); -+ if (ret < 0) -+ return ret; -+ br_write_lock_bh(BR_NETPROTO_LOCK); -+ // see br_input.c -+ br_should_route_hook = ebt_broute; -+ br_write_unlock_bh(BR_NETPROTO_LOCK); -+ return ret; ++ spin_lock_bh(&ebt_log_lock); ++ printk(level_string); ++ printk("%s IN=%s OUT=%s ", info->prefix, in ? in->name : "", ++ out ? out->name : ""); ++ ++ printk("MAC source = "); ++ print_MAC((skb->mac.ethernet)->h_source); ++ printk("MAC dest = "); ++ print_MAC((skb->mac.ethernet)->h_dest); ++ ++ printk("proto = 0x%04x", ntohs(((*skb).mac.ethernet)->h_proto)); ++ ++ if ((info->bitmask & EBT_LOG_IP) && skb->mac.ethernet->h_proto == ++ htons(ETH_P_IP)){ ++ struct iphdr *iph = skb->nh.iph; ++ printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,", ++ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); ++ printk(" IP tos=0x%02X, IP proto=%d", iph->tos, iph->protocol); ++ if (iph->protocol == IPPROTO_TCP || ++ iph->protocol == IPPROTO_UDP) { ++ struct tcpudphdr *ports = (struct tcpudphdr *)(skb->data + iph->ihl*4); ++ ++ if (skb->data + iph->ihl*4 > skb->tail) { ++ printk(" INCOMPLETE TCP/UDP header"); ++ goto out; ++ } ++ printk(" SPT=%u DPT=%u", ntohs(ports->src), ++ ntohs(ports->dst)); ++ } ++ goto out; ++ } ++ ++ if ((info->bitmask & EBT_LOG_ARP) && ++ ((skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) || ++ (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_RARP)))) { ++ struct arphdr * arph = skb->nh.arph; ++ printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d", ++ ntohs(arph->ar_hrd), ntohs(arph->ar_pro), ++ ntohs(arph->ar_op)); ++ /* If it's for Ethernet and the lengths are OK, ++ * then log the ARP payload */ ++ if (arph->ar_hrd == __constant_htons(1) && ++ arph->ar_hln == ETH_ALEN && ++ arph->ar_pln == sizeof(uint32_t)) { ++ struct arppayload *arpp = (struct arppayload *)(skb->data + sizeof(*arph)); ++ ++ if (skb->data + sizeof(*arph) > skb->tail) { ++ printk(" INCOMPLETE ARP header"); ++ goto out; ++ } ++ ++ printk(" ARP MAC SRC="); ++ print_MAC(arpp->mac_src); ++ printk(" ARP IP SRC=%u.%u.%u.%u", ++ myNIPQUAD(arpp->ip_src)); ++ printk(" ARP MAC DST="); ++ print_MAC(arpp->mac_dst); ++ printk(" ARP IP DST=%u.%u.%u.%u", ++ myNIPQUAD(arpp->ip_dst)); ++ } ++ ++ } ++out: ++ printk("\n"); ++ spin_unlock_bh(&ebt_log_lock); ++} ++ ++static struct ebt_watcher log = ++{ ++ {NULL, NULL}, EBT_LOG_WATCHER, ebt_log, ebt_log_check, NULL, ++ THIS_MODULE ++}; ++ ++static int __init init(void) ++{ ++ return ebt_register_watcher(&log); +} + +static void __exit fini(void) +{ -+ br_write_lock_bh(BR_NETPROTO_LOCK); -+ br_should_route_hook = NULL; -+ br_write_unlock_bh(BR_NETPROTO_LOCK); -+ ebt_unregister_table(&broute_table); ++ ebt_unregister_watcher(&log); +} + +module_init(init); +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebtable_filter.c linux-ebtables/net/bridge/netfilter/ebtable_filter.c ---- linux-mips-cvs/net/bridge/netfilter/ebtable_filter.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebtable_filter.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,90 @@ +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_ulog.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,281 @@ +/* -+ * ebtable_filter ++ * netfilter module for userspace bridged Ethernet frames logging daemons + * + * Authors: -+ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * Bart De Schuymer <bdschuym@pandora.be> + * -+ * April, 2002 ++ * November, 2004 ++ * ++ * Based on ipt_ULOG.c, which is ++ * (C) 2000-2002 by Harald Welte <laforge@netfilter.org> ++ * ++ * This module accepts two parameters: ++ * ++ * nlbufsiz: ++ * The parameter specifies how big the buffer for each netlink multicast ++ * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will ++ * get accumulated in the kernel until they are sent to userspace. It is ++ * NOT possible to allocate more than 128kB, and it is strongly discouraged, ++ * because atomically allocating 128kB inside the network rx softirq is not ++ * reliable. Please also keep in mind that this buffer size is allocated for ++ * each nlgroup you are using, so the total kernel memory usage increases ++ * by that factor. ++ * ++ * flushtimeout: ++ * Specify, after how many hundredths of a second the queue should be ++ * flushed even if it is not full yet. + * + */ + -+#include <linux/netfilter_bridge/ebtables.h> +#include <linux/module.h> ++#include <linux/config.h> ++#include <linux/spinlock.h> ++#include <linux/socket.h> ++#include <linux/skbuff.h> ++#include <linux/kernel.h> ++#include <linux/timer.h> ++#include <linux/netlink.h> ++#include <linux/netdevice.h> ++#include <linux/module.h> ++#include <linux/netfilter_bridge/ebtables.h> ++#include <linux/netfilter_bridge/ebt_ulog.h> ++#include <net/sock.h> ++#include "../br_private.h" + -+#define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \ -+ (1 << NF_BR_LOCAL_OUT)) ++#define PRINTR(format, args...) do { if (net_ratelimit()) \ ++ printk(format , ## args); } while (0) + -+static struct ebt_entries initial_chains[] = ++static unsigned int nlbufsiz = 4096; ++MODULE_PARM(nlbufsiz, "i"); ++MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " ++ "(defaults to 4096)"); ++ ++static unsigned int flushtimeout = 10; ++MODULE_PARM(flushtimeout, "i"); ++MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second) " ++ "(defaults to 10)"); ++ ++typedef struct { ++ unsigned int qlen; /* number of nlmsgs' in the skb */ ++ struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ ++ struct sk_buff *skb; /* the pre-allocated skb */ ++ struct timer_list timer; /* the timer function */ ++ spinlock_t lock; /* the per-queue lock */ ++} ebt_ulog_buff_t; ++ ++static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; ++static struct sock *ebtlognl; ++ ++/* send one ulog_buff_t to userspace */ ++static void ulog_send(unsigned int nlgroup) +{ -+ {0, "INPUT", 0, EBT_ACCEPT, 0}, -+ {0, "FORWARD", 0, EBT_ACCEPT, 0}, -+ {0, "OUTPUT", 0, EBT_ACCEPT, 0} -+}; ++ ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup]; + -+static struct ebt_replace initial_table = ++ if (timer_pending(&ub->timer)) ++ del_timer(&ub->timer); ++ ++ /* last nlmsg needs NLMSG_DONE */ ++ if (ub->qlen > 1) ++ ub->lastnlh->nlmsg_type = NLMSG_DONE; ++ ++ NETLINK_CB(ub->skb).dst_groups = 1 << nlgroup; ++ netlink_broadcast(ebtlognl, ub->skb, 0, 1 << nlgroup, GFP_ATOMIC); ++ ++ ub->qlen = 0; ++ ub->skb = NULL; ++} ++ ++/* timer function to flush queue in flushtimeout time */ ++static void ulog_timer(unsigned long data) +{ -+ "filter", FILTER_VALID_HOOKS, 0, 3 * sizeof(struct ebt_entries), -+ { [NF_BR_LOCAL_IN]&initial_chains[0], [NF_BR_FORWARD]&initial_chains[1], -+ [NF_BR_LOCAL_OUT]&initial_chains[2] }, 0, NULL, (char *)initial_chains -+}; ++ spin_lock_bh(&ulog_buffers[data].lock); ++ if (ulog_buffers[data].skb) ++ ulog_send(data); ++ spin_unlock_bh(&ulog_buffers[data].lock); ++} + -+static int check(const struct ebt_table_info *info, unsigned int valid_hooks) ++static struct sk_buff *ulog_alloc_skb(unsigned int size) +{ -+ if (valid_hooks & ~FILTER_VALID_HOOKS) -+ return -EINVAL; -+ return 0; ++ struct sk_buff *skb; ++ ++ skb = alloc_skb(nlbufsiz, GFP_ATOMIC); ++ if (!skb) { ++ PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " ++ "of size %ub!\n", nlbufsiz); ++ if (size < nlbufsiz) { ++ /* try to allocate only as much as we need for ++ * current packet */ ++ skb = alloc_skb(size, GFP_ATOMIC); ++ if (!skb) ++ PRINTR(KERN_ERR "ebt_ulog: can't even allocate " ++ "buffer of size %ub\n", size); ++ } ++ } ++ ++ return skb; +} + -+static struct ebt_table frame_filter = -+{ -+ {NULL, NULL}, "filter", &initial_table, FILTER_VALID_HOOKS, -+ RW_LOCK_UNLOCKED, check, NULL -+}; ++static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *data, unsigned int datalen) ++{ ++ ebt_ulog_packet_msg_t *pm; ++ size_t size, copy_len; ++ struct nlmsghdr *nlh; ++ struct ebt_ulog_info *loginfo = (struct ebt_ulog_info *)data; ++ unsigned int group = loginfo->nlgroup; ++ ebt_ulog_buff_t *ub = &ulog_buffers[group]; ++ spinlock_t *lock = &ub->lock; + -+static unsigned int -+ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in, -+ const struct net_device *out, int (*okfn)(struct sk_buff *)) ++ if ((loginfo->cprange == 0) || ++ (loginfo->cprange > skb->len + ETH_HLEN)) ++ copy_len = skb->len + ETH_HLEN; ++ else ++ copy_len = loginfo->cprange; ++ ++ size = NLMSG_SPACE(sizeof(*pm) + copy_len); ++ ++ spin_lock_bh(lock); ++ ++ if (!ub->skb) { ++ if (!(ub->skb = ulog_alloc_skb(size))) ++ goto alloc_failure; ++ } else if (size > skb_tailroom(ub->skb)) { ++ ulog_send(group); ++ ++ if (!(ub->skb = ulog_alloc_skb(size))) ++ goto alloc_failure; ++ } ++ ++ nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0, ++ size - NLMSG_ALIGN(sizeof(*nlh))); ++ ub->qlen++; ++ ++ pm = NLMSG_DATA(nlh); ++ ++ /* Fill in the ulog data */ ++ do_gettimeofday(&pm->stamp); ++ if (ub->qlen == 1) ++ ub->skb->stamp = pm->stamp; ++ pm->data_len = copy_len; ++ pm->mark = skb->nfmark; ++ pm->hook = hooknr; ++ if (loginfo->prefix != NULL) ++ strcpy(pm->prefix, loginfo->prefix); ++ else ++ *(pm->prefix) = '\0'; ++ ++ if (in) { ++ strcpy(pm->physindev, in->name); ++ strcpy(pm->indev, in->br_port->br->dev.name); ++ } else ++ pm->indev[0] = pm->physindev[0] = '\0'; ++ ++ if (out) { ++ strcpy(pm->physoutdev, out->name); ++ strcpy(pm->outdev, out->br_port->br->dev.name); ++ } else ++ pm->outdev[0] = pm->physoutdev[0] = '\0'; ++ ++ if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) ++ BUG(); ++ ++ if (ub->qlen > 1) ++ ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; ++ ++ ub->lastnlh = nlh; ++ ++ if (ub->qlen >= loginfo->qthreshold) ++ ulog_send(group); ++ else if (!timer_pending(&ub->timer)) { ++ ub->timer.expires = jiffies + flushtimeout * HZ / 100; ++ add_timer(&ub->timer); ++ } ++ ++unlock: ++ spin_unlock_bh(lock); ++ ++ return; ++ ++nlmsg_failure: ++ PRINTR(KERN_ERR "ebt_ULOG: error during NLMSG_PUT.\n"); ++ goto unlock; ++alloc_failure: ++ goto unlock; ++} ++ ++static int ebt_ulog_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) +{ -+ return ebt_do_table(hook, pskb, in, out, &frame_filter); ++ struct ebt_ulog_info *loginfo = (struct ebt_ulog_info *)data; ++ ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) || ++ loginfo->nlgroup > 31) ++ return -EINVAL; ++ ++ loginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; ++ ++ if (loginfo->qthreshold > EBT_ULOG_MAX_QLEN) ++ loginfo->qthreshold = EBT_ULOG_MAX_QLEN; ++ ++ return 0; +} + -+static struct nf_hook_ops ebt_ops_filter[] = { -+ { { NULL, NULL }, ebt_hook, PF_BRIDGE, NF_BR_LOCAL_IN, -+ NF_BR_PRI_FILTER_BRIDGED}, -+ { { NULL, NULL }, ebt_hook, PF_BRIDGE, NF_BR_FORWARD, -+ NF_BR_PRI_FILTER_BRIDGED}, -+ { { NULL, NULL }, ebt_hook, PF_BRIDGE, NF_BR_LOCAL_OUT, -+ NF_BR_PRI_FILTER_OTHER} ++static struct ebt_watcher ulog = { ++ {NULL, NULL}, EBT_ULOG_WATCHER, ebt_ulog, ebt_ulog_check, NULL, ++ THIS_MODULE +}; + +static int __init init(void) +{ -+ int i, j, ret; ++ int i, ret = 0; ++ ++ if (nlbufsiz >= 128*1024) { ++ printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB," ++ " please try a smaller nlbufsiz parameter.\n"); ++ return -EINVAL; ++ } ++ ++ /* initialize ulog_buffers */ ++ for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { ++ init_timer(&ulog_buffers[i].timer); ++ ulog_buffers[i].timer.function = ulog_timer; ++ ulog_buffers[i].timer.data = i; ++ ulog_buffers[i].lock = SPIN_LOCK_UNLOCKED; ++ } ++ ++ ebtlognl = netlink_kernel_create(NETLINK_NFLOG, NULL); ++ if (!ebtlognl) ++ ret = -ENOMEM; ++ else if ((ret = ebt_register_watcher(&ulog))) ++ sock_release(ebtlognl->socket); + -+ ret = ebt_register_table(&frame_filter); -+ if (ret < 0) -+ return ret; -+ for (i = 0; i < sizeof(ebt_ops_filter) / sizeof(ebt_ops_filter[0]); i++) -+ if ((ret = nf_register_hook(&ebt_ops_filter[i])) < 0) -+ goto cleanup; -+ return ret; -+cleanup: -+ for (j = 0; j < i; j++) -+ nf_unregister_hook(&ebt_ops_filter[j]); -+ ebt_unregister_table(&frame_filter); + return ret; +} + +static void __exit fini(void) +{ ++ ebt_ulog_buff_t *ub; + int i; + -+ for (i = 0; i < sizeof(ebt_ops_filter) / sizeof(ebt_ops_filter[0]); i++) -+ nf_unregister_hook(&ebt_ops_filter[i]); -+ ebt_unregister_table(&frame_filter); ++ ebt_unregister_watcher(&ulog); ++ for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { ++ ub = &ulog_buffers[i]; ++ if (timer_pending(&ub->timer)) ++ del_timer(&ub->timer); ++ spin_lock_bh(&ub->lock); ++ if (ub->skb) { ++ kfree_skb(ub->skb); ++ ub->skb = NULL; ++ } ++ spin_unlock_bh(&ub->lock); ++ } ++ sock_release(ebtlognl->socket); +} + +module_init(init); +module_exit(fini); -+EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebtable_nat.c linux-ebtables/net/bridge/netfilter/ebtable_nat.c ---- linux-mips-cvs/net/bridge/netfilter/ebtable_nat.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebtable_nat.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,96 @@ ++MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); ++MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet" ++ " frames"); +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_snat.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,64 @@ +/* -+ * ebtable_nat ++ * ebt_snat + * + * Authors: + * Bart De Schuymer <bart.de.schuymer@pandora.be> + * -+ * April, 2002 ++ * June, 2002 + * + */ + +#include <linux/netfilter_bridge/ebtables.h> ++#include <linux/netfilter_bridge/ebt_nat.h> +#include <linux/module.h> -+#define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \ -+ (1 << NF_BR_POST_ROUTING)) + -+static struct ebt_entries initial_chains[] = ++static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *data, unsigned int datalen) +{ -+ {0, "PREROUTING", 0, EBT_ACCEPT, 0}, -+ {0, "OUTPUT", 0, EBT_ACCEPT, 0}, -+ {0, "POSTROUTING", 0, EBT_ACCEPT, 0} -+}; ++ struct ebt_nat_info *info = (struct ebt_nat_info *) data; + -+static struct ebt_replace initial_table = -+{ -+ "nat", NAT_VALID_HOOKS, 0, 3 * sizeof(struct ebt_entries), -+ { [NF_BR_PRE_ROUTING]&initial_chains[0], [NF_BR_LOCAL_OUT]&initial_chains[1], -+ [NF_BR_POST_ROUTING]&initial_chains[2] }, 0, NULL, (char *)initial_chains -+}; ++ memcpy(((**pskb).mac.ethernet)->h_source, info->mac, ++ ETH_ALEN * sizeof(unsigned char)); ++ return info->target; ++} + -+static int check(const struct ebt_table_info *info, unsigned int valid_hooks) ++static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) +{ -+ if (valid_hooks & ~NAT_VALID_HOOKS) ++ struct ebt_nat_info *info = (struct ebt_nat_info *) data; ++ ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) ++ return -EINVAL; ++ if (BASE_CHAIN && info->target == EBT_RETURN) ++ return -EINVAL; ++ CLEAR_BASE_CHAIN_BIT; ++ if (strcmp(tablename, "nat")) ++ return -EINVAL; ++ if (hookmask & ~(1 << NF_BR_POST_ROUTING)) ++ return -EINVAL; ++ if (INVALID_TARGET) + return -EINVAL; + return 0; +} + -+static struct ebt_table frame_nat = ++static struct ebt_target snat = +{ -+ {NULL, NULL}, "nat", &initial_table, NAT_VALID_HOOKS, -+ RW_LOCK_UNLOCKED, check, NULL ++ {NULL, NULL}, EBT_SNAT_TARGET, ebt_target_snat, ebt_target_snat_check, ++ NULL, THIS_MODULE +}; + -+static unsigned int -+ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in -+ , const struct net_device *out, int (*okfn)(struct sk_buff *)) ++static int __init init(void) +{ -+ return ebt_do_table(hook, pskb, in, out, &frame_nat); ++ return ebt_register_target(&snat); +} + -+static unsigned int -+ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in -+ , const struct net_device *out, int (*okfn)(struct sk_buff *)) ++static void __exit fini(void) +{ -+ return ebt_do_table(hook, pskb, in, out, &frame_nat); ++ ebt_unregister_target(&snat); +} + -+static struct nf_hook_ops ebt_ops_nat[] = { -+ { { NULL, NULL }, ebt_nat_dst, PF_BRIDGE, NF_BR_LOCAL_OUT, -+ NF_BR_PRI_NAT_DST_OTHER}, -+ { { NULL, NULL }, ebt_nat_src, PF_BRIDGE, NF_BR_POST_ROUTING, -+ NF_BR_PRI_NAT_SRC}, -+ { { NULL, NULL }, ebt_nat_dst, PF_BRIDGE, NF_BR_PRE_ROUTING, -+ NF_BR_PRI_NAT_DST_BRIDGED}, ++module_init(init); ++module_exit(fini); ++EXPORT_NO_SYMBOLS; ++MODULE_LICENSE("GPL"); +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebt_dnat.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,65 @@ ++/* ++ * ebt_dnat ++ * ++ * Authors: ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * ++ * June, 2002 ++ * ++ */ ++ ++#include <linux/netfilter_bridge/ebtables.h> ++#include <linux/netfilter_bridge/ebt_nat.h> ++#include <linux/module.h> ++#include <net/sock.h> ++ ++static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *data, unsigned int datalen) ++{ ++ struct ebt_nat_info *info = (struct ebt_nat_info *)data; ++ ++ memcpy(((**pskb).mac.ethernet)->h_dest, info->mac, ++ ETH_ALEN * sizeof(unsigned char)); ++ return info->target; ++} ++ ++static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *data, unsigned int datalen) ++{ ++ struct ebt_nat_info *info = (struct ebt_nat_info *)data; ++ ++ if (BASE_CHAIN && info->target == EBT_RETURN) ++ return -EINVAL; ++ CLEAR_BASE_CHAIN_BIT; ++ if ( (strcmp(tablename, "nat") || ++ (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) && ++ (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) ) ++ return -EINVAL; ++ if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) ++ return -EINVAL; ++ if (INVALID_TARGET) ++ return -EINVAL; ++ return 0; ++} ++ ++static struct ebt_target dnat = ++{ ++ {NULL, NULL}, EBT_DNAT_TARGET, ebt_target_dnat, ebt_target_dnat_check, ++ NULL, THIS_MODULE +}; + +static int __init init(void) +{ -+ int i, ret, j; -+ -+ ret = ebt_register_table(&frame_nat); -+ if (ret < 0) -+ return ret; -+ for (i = 0; i < sizeof(ebt_ops_nat) / sizeof(ebt_ops_nat[0]); i++) -+ if ((ret = nf_register_hook(&ebt_ops_nat[i])) < 0) -+ goto cleanup; -+ return ret; -+cleanup: -+ for (j = 0; j < i; j++) -+ nf_unregister_hook(&ebt_ops_nat[j]); -+ ebt_unregister_table(&frame_nat); -+ return ret; ++ return ebt_register_target(&dnat); +} + +static void __exit fini(void) +{ -+ int i; -+ -+ for (i = 0; i < sizeof(ebt_ops_nat) / sizeof(ebt_ops_nat[0]); i++) -+ nf_unregister_hook(&ebt_ops_nat[i]); -+ ebt_unregister_table(&frame_nat); ++ ebt_unregister_target(&dnat); +} + +module_init(init); +module_exit(fini); +EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/bridge/netfilter/ebtables.c linux-ebtables/net/bridge/netfilter/ebtables.c ---- linux-mips-cvs/net/bridge/netfilter/ebtables.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/bridge/netfilter/ebtables.c 2005-02-07 05:52:50.000000000 +0100 -@@ -0,0 +1,1496 @@ +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/netfilter/ebtables.c 2005-03-14 21:04:05.155913576 +0100 +@@ -0,0 +1,1497 @@ +/* + * ebtables + * @@ -6046,9 +3007,10 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebtables.c linux-ebtables/net/brid + struct ebt_chainstack *cs; + struct ebt_entries *chaininfo; + char *base; -+ struct ebt_table_info *private = table->private; ++ struct ebt_table_info *private; + + read_lock_bh(&table->lock); ++ private = table->private; + cb_base = COUNTER_BASE(private->counters, private->nentries, + cpu_number_map(smp_processor_id())); + if (private->chainstack) @@ -6727,7 +3689,7 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebtables.c linux-ebtables/net/brid + 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 size of the allocated space is right + // - all valid hooks have a corresponding chain @@ -7365,44 +4327,964 @@ diff -Nur linux-mips-cvs/net/bridge/netfilter/ebtables.c linux-ebtables/net/brid +module_init(init); +module_exit(fini); +MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/core/dev.c linux-ebtables/net/core/dev.c ---- linux-mips-cvs/net/core/dev.c 2004-04-16 05:14:21.000000000 +0200 -+++ linux-ebtables/net/core/dev.c 2005-02-07 05:52:50.000000000 +0100 -@@ -1426,7 +1426,7 @@ - +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebtables.h 2005-03-14 21:24:12.000000000 +0100 +@@ -0,0 +1,361 @@ ++/* ++ * ebtables ++ * ++ * Authors: ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * ++ * ebtables.c,v 2.0, September, 2002 ++ * ++ * This code is stongly inspired on the iptables code which is ++ * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling ++ */ ++ ++#ifndef __LINUX_BRIDGE_EFF_H ++#define __LINUX_BRIDGE_EFF_H ++#include <linux/if.h> ++#include <linux/netfilter_bridge.h> ++#include <linux/if_ether.h> ++ ++#define EBT_TABLE_MAXNAMELEN 32 ++#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN ++#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN ++ ++// verdicts >0 are "branches" ++#define EBT_ACCEPT -1 ++#define EBT_DROP -2 ++#define EBT_CONTINUE -3 ++#define EBT_RETURN -4 ++#define NUM_STANDARD_TARGETS 4 ++ ++struct ebt_counter ++{ ++ uint64_t pcnt; ++ uint64_t bcnt; ++}; ++ ++struct ebt_entries { ++ // this field is always set to zero ++ // See EBT_ENTRY_OR_ENTRIES. ++ // Must be same size as ebt_entry.bitmask ++ unsigned int distinguisher; ++ // the chain name ++ char name[EBT_CHAIN_MAXNAMELEN]; ++ // counter offset for this chain ++ unsigned int counter_offset; ++ // one standard (accept, drop, return) per hook ++ int policy; ++ // nr. of entries ++ unsigned int nentries; ++ // entry list ++ char data[0]; ++}; ++ ++// used for the bitmask of struct ebt_entry ++ ++// This is a hack to make a difference between an ebt_entry struct and an ++// ebt_entries struct when traversing the entries from start to end. ++// Using this simplifies the code alot, while still being able to use ++// ebt_entries. ++// Contrary, iptables doesn't use something like ebt_entries and therefore uses ++// different techniques for naming the policy and such. So, iptables doesn't ++// need a hack like this. ++#define EBT_ENTRY_OR_ENTRIES 0x01 ++// these are the normal masks ++#define EBT_NOPROTO 0x02 ++#define EBT_802_3 0x04 ++#define EBT_SOURCEMAC 0x08 ++#define EBT_DESTMAC 0x10 ++#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \ ++ | EBT_ENTRY_OR_ENTRIES) ++ ++#define EBT_IPROTO 0x01 ++#define EBT_IIN 0x02 ++#define EBT_IOUT 0x04 ++#define EBT_ISOURCE 0x8 ++#define EBT_IDEST 0x10 ++#define EBT_ILOGICALIN 0x20 ++#define EBT_ILOGICALOUT 0x40 ++#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \ ++ | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST) ++ ++struct ebt_entry_match ++{ ++ union { ++ char name[EBT_FUNCTION_MAXNAMELEN]; ++ struct ebt_match *match; ++ } u; ++ // size of data ++ unsigned int match_size; ++ unsigned char data[0]; ++}; ++ ++struct ebt_entry_watcher ++{ ++ union { ++ char name[EBT_FUNCTION_MAXNAMELEN]; ++ struct ebt_watcher *watcher; ++ } u; ++ // size of data ++ unsigned int watcher_size; ++ unsigned char data[0]; ++}; ++ ++struct ebt_entry_target ++{ ++ union { ++ char name[EBT_FUNCTION_MAXNAMELEN]; ++ struct ebt_target *target; ++ } u; ++ // size of data ++ unsigned int target_size; ++ unsigned char data[0]; ++}; ++ ++#define EBT_STANDARD_TARGET "standard" ++struct ebt_standard_target ++{ ++ struct ebt_entry_target target; ++ int verdict; ++}; ++ ++// one entry ++struct ebt_entry { ++ // this needs to be the first field ++ unsigned int bitmask; ++ unsigned int invflags; ++ uint16_t ethproto; ++ // the physical in-dev ++ char in[IFNAMSIZ]; ++ // the logical in-dev ++ char logical_in[IFNAMSIZ]; ++ // the physical out-dev ++ char out[IFNAMSIZ]; ++ // the logical out-dev ++ char logical_out[IFNAMSIZ]; ++ unsigned char sourcemac[ETH_ALEN]; ++ unsigned char sourcemsk[ETH_ALEN]; ++ unsigned char destmac[ETH_ALEN]; ++ unsigned char destmsk[ETH_ALEN]; ++ // sizeof ebt_entry + matches ++ unsigned int watchers_offset; ++ // sizeof ebt_entry + matches + watchers ++ unsigned int target_offset; ++ // sizeof ebt_entry + matches + watchers + target ++ unsigned int next_offset; ++ unsigned char elems[0]; ++}; ++ ++struct ebt_replace ++{ ++ char name[EBT_TABLE_MAXNAMELEN]; ++ unsigned int valid_hooks; ++ // nr of rules in the table ++ unsigned int nentries; ++ // total size of the entries ++ unsigned int entries_size; ++ // start of the chains ++ struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; ++ // nr of counters userspace expects back ++ unsigned int num_counters; ++ // where the kernel will put the old counters ++ struct ebt_counter *counters; ++ char *entries; ++}; ++ ++// [gs]etsockopt numbers ++#define EBT_BASE_CTL 128 ++ ++#define EBT_SO_SET_ENTRIES (EBT_BASE_CTL) ++#define EBT_SO_SET_COUNTERS (EBT_SO_SET_ENTRIES+1) ++#define EBT_SO_SET_MAX (EBT_SO_SET_COUNTERS+1) ++ ++#define EBT_SO_GET_INFO (EBT_BASE_CTL) ++#define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1) ++#define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1) ++#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1) ++#define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1) ++ ++#ifdef __KERNEL__ ++ ++// return values for match() functions ++#define EBT_MATCH 0 ++#define EBT_NOMATCH 1 ++ ++struct ebt_match ++{ ++ struct list_head list; ++ const char name[EBT_FUNCTION_MAXNAMELEN]; ++ // 0 == it matches ++ int (*match)(const struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, const void *matchdata, ++ unsigned int datalen); ++ // 0 == let it in ++ int (*check)(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *matchdata, unsigned int datalen); ++ void (*destroy)(void *matchdata, unsigned int datalen); ++ struct module *me; ++}; ++ ++struct ebt_watcher ++{ ++ struct list_head list; ++ const char name[EBT_FUNCTION_MAXNAMELEN]; ++ void (*watcher)(const struct sk_buff *skb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *watcherdata, unsigned int datalen); ++ // 0 == let it in ++ int (*check)(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *watcherdata, unsigned int datalen); ++ void (*destroy)(void *watcherdata, unsigned int datalen); ++ struct module *me; ++}; ++ ++struct ebt_target ++{ ++ struct list_head list; ++ const char name[EBT_FUNCTION_MAXNAMELEN]; ++ // returns one of the standard verdicts ++ int (*target)(struct sk_buff **pskb, unsigned int hooknr, ++ const struct net_device *in, const struct net_device *out, ++ const void *targetdata, unsigned int datalen); ++ // 0 == let it in ++ int (*check)(const char *tablename, unsigned int hookmask, ++ const struct ebt_entry *e, void *targetdata, unsigned int datalen); ++ void (*destroy)(void *targetdata, unsigned int datalen); ++ struct module *me; ++}; ++ ++// used for jumping from and into user defined chains (udc) ++struct ebt_chainstack ++{ ++ struct ebt_entries *chaininfo; // pointer to chain data ++ struct ebt_entry *e; // pointer to entry data ++ unsigned int n; // n'th entry ++}; ++ ++struct ebt_table_info ++{ ++ // total size of the entries ++ unsigned int entries_size; ++ unsigned int nentries; ++ // pointers to the start of the chains ++ struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; ++ // room to maintain the stack used for jumping from and into udc ++ struct ebt_chainstack **chainstack; ++ char *entries; ++ struct ebt_counter counters[0] ____cacheline_aligned; ++}; ++ ++struct ebt_table ++{ ++ struct list_head list; ++ char name[EBT_TABLE_MAXNAMELEN]; ++ struct ebt_replace *table; ++ unsigned int valid_hooks; ++ rwlock_t lock; ++ // e.g. could be the table explicitly only allows certain ++ // matches, targets, ... 0 == let it in ++ int (*check)(const struct ebt_table_info *info, ++ unsigned int valid_hooks); ++ // the data used by the kernel ++ struct ebt_table_info *private; ++}; ++ ++#define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_entry_target)-1)) & \ ++ ~(__alignof__(struct ebt_entry_target)-1)) ++extern int ebt_register_table(struct ebt_table *table); ++extern void ebt_unregister_table(struct ebt_table *table); ++extern int ebt_register_match(struct ebt_match *match); ++extern void ebt_unregister_match(struct ebt_match *match); ++extern int ebt_register_watcher(struct ebt_watcher *watcher); ++extern void ebt_unregister_watcher(struct ebt_watcher *watcher); ++extern int ebt_register_target(struct ebt_target *target); ++extern void ebt_unregister_target(struct ebt_target *target); ++extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ struct ebt_table *table); ++ ++ // Used in the kernel match() functions ++#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) ++// True if the hook mask denotes that the rule is in a base chain, ++// used in the check() functions ++#define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) ++// Clear the bit in the hook mask that tells if the rule is on a base chain ++#define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) ++// True if the target is not a standard target ++#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) ++ ++#endif /* __KERNEL__ */ ++ ++// blatently stolen from ip_tables.h ++// fn returns 0 to continue iteration ++#define EBT_MATCH_ITERATE(e, fn, args...) \ ++({ \ ++ unsigned int __i; \ ++ int __ret = 0; \ ++ struct ebt_entry_match *__match; \ ++ \ ++ for (__i = sizeof(struct ebt_entry); \ ++ __i < (e)->watchers_offset; \ ++ __i += __match->match_size + \ ++ sizeof(struct ebt_entry_match)) { \ ++ __match = (void *)(e) + __i; \ ++ \ ++ __ret = fn(__match , ## args); \ ++ if (__ret != 0) \ ++ break; \ ++ } \ ++ if (__ret == 0) { \ ++ if (__i != (e)->watchers_offset) \ ++ __ret = -EINVAL; \ ++ } \ ++ __ret; \ ++}) ++ ++#define EBT_WATCHER_ITERATE(e, fn, args...) \ ++({ \ ++ unsigned int __i; \ ++ int __ret = 0; \ ++ struct ebt_entry_watcher *__watcher; \ ++ \ ++ for (__i = e->watchers_offset; \ ++ __i < (e)->target_offset; \ ++ __i += __watcher->watcher_size + \ ++ sizeof(struct ebt_entry_watcher)) { \ ++ __watcher = (void *)(e) + __i; \ ++ \ ++ __ret = fn(__watcher , ## args); \ ++ if (__ret != 0) \ ++ break; \ ++ } \ ++ if (__ret == 0) { \ ++ if (__i != (e)->target_offset) \ ++ __ret = -EINVAL; \ ++ } \ ++ __ret; \ ++}) ++ ++#define EBT_ENTRY_ITERATE(entries, size, fn, args...) \ ++({ \ ++ unsigned int __i; \ ++ int __ret = 0; \ ++ struct ebt_entry *__entry; \ ++ \ ++ for (__i = 0; __i < (size);) { \ ++ __entry = (void *)(entries) + __i; \ ++ __ret = fn(__entry , ## args); \ ++ if (__ret != 0) \ ++ break; \ ++ if (__entry->bitmask != 0) \ ++ __i += __entry->next_offset; \ ++ else \ ++ __i += sizeof(struct ebt_entries); \ ++ } \ ++ if (__ret == 0) { \ ++ if (__i != (size)) \ ++ __ret = -EINVAL; \ ++ } \ ++ __ret; \ ++}) ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_among.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,65 @@ ++#ifndef __LINUX_BRIDGE_EBT_AMONG_H ++#define __LINUX_BRIDGE_EBT_AMONG_H ++ ++#define EBT_AMONG_DST 0x01 ++#define EBT_AMONG_SRC 0x02 ++ ++/* Grzegorz Borowiak <grzes@gnu.univ.gda.pl> 2003 ++ * ++ * Write-once-read-many hash table, used for checking if a given ++ * MAC address belongs to a set or not and possibly for checking ++ * if it is related with a given IPv4 address. ++ * ++ * The hash value of an address is its last byte. ++ * ++ * In real-world ethernet addresses, values of the last byte are ++ * evenly distributed and there is no need to consider other bytes. ++ * It would only slow the routines down. ++ * ++ * For MAC address comparison speedup reasons, we introduce a trick. ++ * MAC address is mapped onto an array of two 32-bit integers. ++ * This pair of integers is compared with MAC addresses in the ++ * hash table, which are stored also in form of pairs of integers ++ * (in `cmp' array). This is quick as it requires only two elementary ++ * number comparisons in worst case. Further, we take advantage of ++ * fact that entropy of 3 last bytes of address is larger than entropy ++ * of 3 first bytes. So first we compare 4 last bytes of addresses and ++ * if they are the same we compare 2 first. ++ * ++ * Yes, it is a memory overhead, but in 2003 AD, who cares? ++ */ ++ ++struct ebt_mac_wormhash_tuple ++{ ++ uint32_t cmp[2]; ++ uint32_t ip; ++}; ++ ++struct ebt_mac_wormhash ++{ ++ int table[257]; ++ int poolsize; ++ struct ebt_mac_wormhash_tuple pool[0]; ++}; ++ ++#define ebt_mac_wormhash_size(x) ((x) ? sizeof(struct ebt_mac_wormhash) \ ++ + (x)->poolsize * sizeof(struct ebt_mac_wormhash_tuple) : 0) ++ ++struct ebt_among_info ++{ ++ int wh_dst_ofs; ++ int wh_src_ofs; ++ int bitmask; ++}; ++ ++#define EBT_AMONG_DST_NEG 0x1 ++#define EBT_AMONG_SRC_NEG 0x2 ++ ++#define ebt_among_wh_dst(x) ((x)->wh_dst_ofs ? \ ++ (struct ebt_mac_wormhash*)((char*)(x) + (x)->wh_dst_ofs) : NULL) ++#define ebt_among_wh_src(x) ((x)->wh_src_ofs ? \ ++ (struct ebt_mac_wormhash*)((char*)(x) + (x)->wh_src_ofs) : NULL) ++ ++#define EBT_AMONG_MATCH "among" ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_limit.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,23 @@ ++#ifndef __LINUX_BRIDGE_EBT_LIMIT_H ++#define __LINUX_BRIDGE_EBT_LIMIT_H ++ ++#define EBT_LIMIT_MATCH "limit" ++ ++/* timings are in milliseconds. */ ++#define EBT_LIMIT_SCALE 10000 ++ ++/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 ++ seconds, or one every 59 hours. */ ++ ++struct ebt_limit_info ++{ ++ u_int32_t avg; /* Average secs between packets * scale */ ++ u_int32_t burst; /* Period multiplier for upper limit. */ ++ ++ /* Used internally by the kernel */ ++ unsigned long prev; ++ u_int32_t credit; ++ u_int32_t credit_cap, cost; ++}; ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_arpreply.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,11 @@ ++#ifndef __LINUX_BRIDGE_EBT_ARPREPLY_H ++#define __LINUX_BRIDGE_EBT_ARPREPLY_H ++ ++struct ebt_arpreply_info ++{ ++ unsigned char mac[ETH_ALEN]; ++ int target; ++}; ++#define EBT_ARPREPLY_TARGET "arpreply" ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_802_3.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,60 @@ ++#ifndef __LINUX_BRIDGE_EBT_802_3_H ++#define __LINUX_BRIDGE_EBT_802_3_H ++ ++#define EBT_802_3_SAP 0x01 ++#define EBT_802_3_TYPE 0x02 ++ ++#define EBT_802_3_MATCH "802_3" ++ ++/* ++ * If frame has DSAP/SSAP value 0xaa you must check the SNAP type ++ * to discover what kind of packet we're carrying. ++ */ ++#define CHECK_TYPE 0xaa ++ ++/* ++ * Control field may be one or two bytes. If the first byte has ++ * the value 0x03 then the entire length is one byte, otherwise it is two. ++ * One byte controls are used in Unnumbered Information frames. ++ * Two byte controls are used in Numbered Information frames. ++ */ ++#define IS_UI 0x03 ++ ++#define EBT_802_3_MASK (EBT_802_3_SAP | EBT_802_3_TYPE | EBT_802_3) ++ ++/* ui has one byte ctrl, ni has two */ ++struct hdr_ui { ++ uint8_t dsap; ++ uint8_t ssap; ++ uint8_t ctrl; ++ uint8_t orig[3]; ++ uint16_t type; ++}; ++ ++struct hdr_ni { ++ uint8_t dsap; ++ uint8_t ssap; ++ uint16_t ctrl; ++ uint8_t orig[3]; ++ uint16_t type; ++}; ++ ++struct ebt_802_3_hdr { ++ uint8_t daddr[6]; ++ uint8_t saddr[6]; ++ uint16_t len; ++ union { ++ struct hdr_ui ui; ++ struct hdr_ni ni; ++ } llc; ++}; ++ ++struct ebt_802_3_info ++{ ++ uint8_t sap; ++ uint16_t type; ++ uint8_t bitmask; ++ uint8_t invflags; ++}; ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_arp.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,32 @@ ++#ifndef __LINUX_BRIDGE_EBT_ARP_H ++#define __LINUX_BRIDGE_EBT_ARP_H ++ ++#define EBT_ARP_OPCODE 0x01 ++#define EBT_ARP_HTYPE 0x02 ++#define EBT_ARP_PTYPE 0x04 ++#define EBT_ARP_SRC_IP 0x08 ++#define EBT_ARP_DST_IP 0x10 ++#define EBT_ARP_SRC_MAC 0x20 ++#define EBT_ARP_DST_MAC 0x40 ++#define EBT_ARP_MASK (EBT_ARP_OPCODE | EBT_ARP_HTYPE | EBT_ARP_PTYPE | \ ++ EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC) ++#define EBT_ARP_MATCH "arp" ++ ++struct ebt_arp_info ++{ ++ uint16_t htype; ++ uint16_t ptype; ++ uint16_t opcode; ++ uint32_t saddr; ++ uint32_t smsk; ++ uint32_t daddr; ++ uint32_t dmsk; ++ unsigned char smaddr[ETH_ALEN]; ++ unsigned char smmsk[ETH_ALEN]; ++ unsigned char dmaddr[ETH_ALEN]; ++ unsigned char dmmsk[ETH_ALEN]; ++ uint8_t bitmask; ++ uint8_t invflags; ++}; ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_ip.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,43 @@ ++/* ++ * ebt_ip ++ * ++ * Authors: ++ * Bart De Schuymer <bart.de.schuymer@pandora.be> ++ * ++ * April, 2002 ++ * ++ * Changes: ++ * added ip-sport and ip-dport ++ * Innominate Security Technologies AG <mhopf@innominate.com> ++ * September, 2002 ++ */ ++ ++#ifndef __LINUX_BRIDGE_EBT_IP_H ++#define __LINUX_BRIDGE_EBT_IP_H ++ ++#define EBT_IP_SOURCE 0x01 ++#define EBT_IP_DEST 0x02 ++#define EBT_IP_TOS 0x04 ++#define EBT_IP_PROTO 0x08 ++#define EBT_IP_SPORT 0x10 ++#define EBT_IP_DPORT 0x20 ++#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ ++ EBT_IP_SPORT | EBT_IP_DPORT ) ++#define EBT_IP_MATCH "ip" ++ ++// the same values are used for the invflags ++struct ebt_ip_info ++{ ++ uint32_t saddr; ++ uint32_t daddr; ++ uint32_t smsk; ++ uint32_t dmsk; ++ uint8_t tos; ++ uint8_t protocol; ++ uint8_t bitmask; ++ uint8_t invflags; ++ uint16_t sport[2]; ++ uint16_t dport[2]; ++}; ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_pkttype.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,11 @@ ++#ifndef __LINUX_BRIDGE_EBT_PKTTYPE_H ++#define __LINUX_BRIDGE_EBT_PKTTYPE_H ++ ++struct ebt_pkttype_info ++{ ++ uint8_t pkt_type; ++ uint8_t invert; ++}; ++#define EBT_PKTTYPE_MATCH "pkttype" ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_stp.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,46 @@ ++#ifndef __LINUX_BRIDGE_EBT_STP_H ++#define __LINUX_BRIDGE_EBT_STP_H ++ ++#define EBT_STP_TYPE 0x0001 ++ ++#define EBT_STP_FLAGS 0x0002 ++#define EBT_STP_ROOTPRIO 0x0004 ++#define EBT_STP_ROOTADDR 0x0008 ++#define EBT_STP_ROOTCOST 0x0010 ++#define EBT_STP_SENDERPRIO 0x0020 ++#define EBT_STP_SENDERADDR 0x0040 ++#define EBT_STP_PORT 0x0080 ++#define EBT_STP_MSGAGE 0x0100 ++#define EBT_STP_MAXAGE 0x0200 ++#define EBT_STP_HELLOTIME 0x0400 ++#define EBT_STP_FWDD 0x0800 ++ ++#define EBT_STP_MASK 0x0fff ++#define EBT_STP_CONFIG_MASK 0x0ffe ++ ++#define EBT_STP_MATCH "stp" ++ ++struct ebt_stp_config_info ++{ ++ uint8_t flags; ++ uint16_t root_priol, root_priou; ++ char root_addr[6], root_addrmsk[6]; ++ uint32_t root_costl, root_costu; ++ uint16_t sender_priol, sender_priou; ++ char sender_addr[6], sender_addrmsk[6]; ++ uint16_t portl, portu; ++ uint16_t msg_agel, msg_ageu; ++ uint16_t max_agel, max_ageu; ++ uint16_t hello_timel, hello_timeu; ++ uint16_t forward_delayl, forward_delayu; ++}; ++ ++struct ebt_stp_info ++{ ++ uint8_t type; ++ struct ebt_stp_config_info config; ++ uint16_t bitmask; ++ uint16_t invflags; ++}; ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_vlan.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,20 @@ ++#ifndef __LINUX_BRIDGE_EBT_VLAN_H ++#define __LINUX_BRIDGE_EBT_VLAN_H ++ ++#define EBT_VLAN_ID 0x01 ++#define EBT_VLAN_PRIO 0x02 ++#define EBT_VLAN_ENCAP 0x04 ++#define EBT_VLAN_MASK (EBT_VLAN_ID | EBT_VLAN_PRIO | EBT_VLAN_ENCAP) ++#define EBT_VLAN_MATCH "vlan" ++ ++struct ebt_vlan_info { ++ uint16_t id; /* VLAN ID {1-4095} */ ++ uint8_t prio; /* VLAN User Priority {0-7} */ ++ uint16_t encap; /* VLAN Encapsulated frame code {0-65535} */ ++ uint8_t bitmask; /* Args bitmask bit 1=1 - ID arg, ++ bit 2=1 User-Priority arg, bit 3=1 encap*/ ++ uint8_t invflags; /* Inverse bitmask bit 1=1 - inversed ID arg, ++ bit 2=1 - inversed Pirority arg */ ++}; ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_log.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,17 @@ ++#ifndef __LINUX_BRIDGE_EBT_LOG_H ++#define __LINUX_BRIDGE_EBT_LOG_H ++ ++#define EBT_LOG_IP 0x01 // if the frame is made by ip, log the ip information ++#define EBT_LOG_ARP 0x02 ++#define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP) ++#define EBT_LOG_PREFIX_SIZE 30 ++#define EBT_LOG_WATCHER "log" ++ ++struct ebt_log_info ++{ ++ uint8_t loglevel; ++ uint8_t prefix[EBT_LOG_PREFIX_SIZE]; ++ uint32_t bitmask; ++}; ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_ulog.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,33 @@ ++#ifndef _EBT_ULOG_H ++#define _EBT_ULOG_H ++ ++#define EBT_ULOG_DEFAULT_NLGROUP 0 ++#define EBT_ULOG_DEFAULT_QTHRESHOLD 1 ++#define EBT_ULOG_MAXNLGROUPS 32 /* hardcoded netlink max */ ++#define EBT_ULOG_PREFIX_LEN 32 ++#define EBT_ULOG_MAX_QLEN 50 ++#define EBT_ULOG_WATCHER "ulog" ++ ++struct ebt_ulog_info { ++ uint32_t nlgroup; ++ unsigned int cprange; ++ unsigned int qthreshold; ++ char prefix[EBT_ULOG_PREFIX_LEN]; ++}; ++ ++typedef struct ebt_ulog_packet_msg { ++ char indev[IFNAMSIZ]; ++ char outdev[IFNAMSIZ]; ++ char physindev[IFNAMSIZ]; ++ char physoutdev[IFNAMSIZ]; ++ char prefix[EBT_ULOG_PREFIX_LEN]; ++ struct timeval stamp; ++ unsigned long mark; ++ unsigned int hook; ++ size_t data_len; ++ /* The complete packet, including Ethernet header and perhaps ++ * the VLAN header is appended */ ++ unsigned char data[0] __attribute__ ((aligned (__alignof__(int)))); ++} ebt_ulog_packet_msg_t; ++ ++#endif /* _EBT_ULOG_H */ +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_nat.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,13 @@ ++#ifndef __LINUX_BRIDGE_EBT_NAT_H ++#define __LINUX_BRIDGE_EBT_NAT_H ++ ++struct ebt_nat_info ++{ ++ unsigned char mac[ETH_ALEN]; ++ // EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN ++ int target; ++}; ++#define EBT_SNAT_TARGET "snat" ++#define EBT_DNAT_TARGET "dnat" ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_redirect.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,11 @@ ++#ifndef __LINUX_BRIDGE_EBT_REDIRECT_H ++#define __LINUX_BRIDGE_EBT_REDIRECT_H ++ ++struct ebt_redirect_info ++{ ++ // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN ++ int target; ++}; ++#define EBT_REDIRECT_TARGET "redirect" ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_mark_m.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,15 @@ ++#ifndef __LINUX_BRIDGE_EBT_MARK_M_H ++#define __LINUX_BRIDGE_EBT_MARK_M_H ++ ++#define EBT_MARK_AND 0x01 ++#define EBT_MARK_OR 0x02 ++#define EBT_MARK_MASK (EBT_MARK_AND | EBT_MARK_OR) ++struct ebt_mark_m_info ++{ ++ unsigned long mark, mask; ++ uint8_t invert; ++ uint8_t bitmask; ++}; ++#define EBT_MARK_MATCH "mark_m" ++ ++#endif +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_bridge/ebt_mark_t.h 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,12 @@ ++#ifndef __LINUX_BRIDGE_EBT_MARK_T_H ++#define __LINUX_BRIDGE_EBT_MARK_T_H ++ ++struct ebt_mark_t_info ++{ ++ unsigned long mark; ++ // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN ++ int target; ++}; ++#define EBT_MARK_TARGET "mark" ++ ++#endif +--- linux-2.4.29/include/linux/netfilter.h 2005-01-19 15:10:12.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter.h 2005-03-14 21:11:36.000000000 +0100 +@@ -17,7 +17,8 @@ + #define NF_STOLEN 2 + #define NF_QUEUE 3 + #define NF_REPEAT 4 +-#define NF_MAX_VERDICT NF_REPEAT ++#define NF_STOP 5 ++#define NF_MAX_VERDICT NF_STOP - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) --void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; -+int (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; + /* Generic cache responses from hook functions. + <= 0x2000 is used for protocol-flags. */ +@@ -118,17 +119,34 @@ extern struct list_head nf_hooks[NPROTO] + /* This is gross, but inline doesn't cut it for avoiding the function + call in fast path: gcc doesn't inline (needs value tracking?). --RR */ + #ifdef CONFIG_NETFILTER_DEBUG +-#define NF_HOOK nf_hook_slow ++#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \ ++({int __ret; \ ++if ((__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \ ++ __ret = (okfn)(skb); \ ++__ret;}) ++#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \ ++({int __ret; \ ++if ((__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1) \ ++ __ret = (okfn)(skb); \ ++__ret;}) + #else +-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \ +-(list_empty(&nf_hooks[(pf)][(hook)]) \ +- ? (okfn)(skb) \ +- : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn))) ++#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \ ++({int __ret; \ ++if (list_empty(&nf_hooks[pf][hook]) || \ ++ (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \ ++ __ret = (okfn)(skb); \ ++__ret;}) ++#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \ ++({int __ret; \ ++if (list_empty(&nf_hooks[pf][hook]) || \ ++ (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1) \ ++ __ret = (okfn)(skb); \ ++__ret;}) #endif - static __inline__ int handle_bridge(struct sk_buff *skb, -@@ -1443,7 +1443,6 @@ - } - } - -- br_handle_frame_hook(skb); - return ret; - } +-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, ++int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, + struct net_device *indev, struct net_device *outdev, +- int (*okfn)(struct sk_buff *)); ++ int (*okfn)(struct sk_buff *), int thresh); -@@ -1503,7 +1502,12 @@ - #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - if (skb->dev->br_port != NULL && br_handle_frame_hook != NULL && - skb->pkt_type != PACKET_LOOPBACK) { -- return handle_bridge(skb, pt_prev); -+ int ret; + /* Call setsockopt() */ + int nf_setsockopt(struct sock *sk, int pf, int optval, char *opt, +--- linux-2.4.29/include/linux/netfilter_ipv4.h 2002-02-25 20:38:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_ipv4.h 2005-03-14 21:11:36.000000000 +0100 +@@ -52,8 +52,10 @@ + enum nf_ip_hook_priorities { + NF_IP_PRI_FIRST = INT_MIN, + NF_IP_PRI_CONNTRACK = -200, ++ NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175, + NF_IP_PRI_MANGLE = -150, + NF_IP_PRI_NAT_DST = -100, ++ NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50, + NF_IP_PRI_FILTER = 0, + NF_IP_PRI_NAT_SRC = 100, + NF_IP_PRI_LAST = INT_MAX, +--- linux-2.4.29/include/linux/netfilter_ipv6.h 2001-01-02 01:17:54.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_ipv6.h 2005-03-14 21:24:11.000000000 +0100 +@@ -57,8 +57,10 @@ + enum nf_ip6_hook_priorities { + NF_IP6_PRI_FIRST = INT_MIN, + NF_IP6_PRI_CONNTRACK = -200, ++ NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175, + NF_IP6_PRI_MANGLE = -150, + NF_IP6_PRI_NAT_DST = -100, ++ NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50, + NF_IP6_PRI_FILTER = 0, + NF_IP6_PRI_NAT_SRC = 100, + NF_IP6_PRI_LAST = INT_MAX, +--- linux-2.4.29/include/linux/skbuff.h 2004-08-08 01:26:06.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/include/linux/skbuff.h 2005-03-14 21:07:31.000000000 +0100 +@@ -92,6 +92,20 @@ struct nf_conntrack { + struct nf_ct_info { + struct nf_conntrack *master; + }; + -+ ret = handle_bridge(skb, pt_prev); -+ if (br_handle_frame_hook(skb) == 0) -+ return ret; -+ pt_prev = NULL; - } ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++struct nf_bridge_info { ++ atomic_t use; ++ struct net_device *physindev; ++ struct net_device *physoutdev; ++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) ++ struct net_device *netoutdev; ++#endif ++ unsigned int mask; ++ unsigned long data[32 / sizeof(unsigned long)]; ++}; ++#endif ++ + #endif + + struct sk_buff_head { +@@ -208,6 +222,9 @@ struct sk_buff { + #ifdef CONFIG_NETFILTER_DEBUG + unsigned int nf_debug; #endif ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ struct nf_bridge_info *nf_bridge; /* Saved data about a bridged frame - see br_netfilter.c */ ++#endif + #endif /*CONFIG_NETFILTER*/ -diff -Nur linux-mips-cvs/net/core/netfilter.c linux-ebtables/net/core/netfilter.c ---- linux-mips-cvs/net/core/netfilter.c 2005-01-20 03:19:25.000000000 +0100 -+++ linux-ebtables/net/core/netfilter.c 2005-02-07 05:52:50.000000000 +0100 -@@ -342,10 +342,15 @@ + #if defined(CONFIG_HIPPI) +@@ -1175,6 +1192,20 @@ nf_reset(struct sk_buff *skb) + skb->nf_debug = 0; + #endif + } ++ ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) ++{ ++ if (nf_bridge && atomic_dec_and_test(&nf_bridge->use)) ++ kfree(nf_bridge); ++} ++static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) ++{ ++ if (nf_bridge) ++ atomic_inc(&nf_bridge->use); ++} ++#endif ++ + #else /* CONFIG_NETFILTER */ + static inline void nf_reset(struct sk_buff *skb) {} + #endif /* CONFIG_NETFILTER */ +--- linux-2.4.29/net/core/netfilter.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/core/netfilter.c 2005-03-14 21:21:41.825275416 +0100 +@@ -342,32 +342,29 @@ static unsigned int nf_iterate(struct li const struct net_device *indev, const struct net_device *outdev, struct list_head **i, @@ -7410,16 +5292,48 @@ diff -Nur linux-mips-cvs/net/core/netfilter.c linux-ebtables/net/core/netfilter. + int (*okfn)(struct sk_buff *), + int hook_thresh) { ++ unsigned int verdict; ++ for (*i = (*i)->next; *i != head; *i = (*i)->next) { struct nf_hook_ops *elem = (struct nf_hook_ops *)*i; -+ +- switch (elem->hook(hook, skb, indev, outdev, okfn)) { +- case NF_QUEUE: +- return NF_QUEUE; +- +- case NF_STOLEN: +- return NF_STOLEN; +- +- case NF_DROP: +- return NF_DROP; + +- case NF_REPEAT: +- *i = (*i)->prev; +- break; + if (hook_thresh > elem->priority) + continue; -+ - switch (elem->hook(hook, skb, indev, outdev, okfn)) { - case NF_QUEUE: - return NF_QUEUE; -@@ -413,6 +418,10 @@ + ++ verdict = elem->hook(hook, skb, indev, outdev, okfn); ++ if (verdict != NF_ACCEPT) { + #ifdef CONFIG_NETFILTER_DEBUG +- case NF_ACCEPT: +- break; +- +- default: +- NFDEBUG("Evil return from %p(%u).\n", +- elem->hook, hook); ++ if (unlikely(verdict > NF_MAX_VERDICT)) { ++ NFDEBUG("Evil return from %p(%u).\n", ++ elem->hook, hook); ++ continue; ++ } + #endif ++ if (verdict != NF_REPEAT) ++ return verdict; ++ *i = (*i)->prev; + } + } + return NF_ACCEPT; +@@ -413,6 +410,10 @@ static void nf_queue(struct sk_buff *skb { int status; struct nf_info *info; @@ -7430,7 +5344,7 @@ diff -Nur linux-mips-cvs/net/core/netfilter.c linux-ebtables/net/core/netfilter. if (!queue_handler[pf].outfn) { kfree_skb(skb); -@@ -435,11 +444,24 @@ +@@ -435,36 +436,52 @@ static void nf_queue(struct sk_buff *skb if (indev) dev_hold(indev); if (outdev) dev_hold(outdev); @@ -7455,8 +5369,13 @@ diff -Nur linux-mips-cvs/net/core/netfilter.c linux-ebtables/net/core/netfilter. kfree(info); kfree_skb(skb); return; -@@ -449,7 +471,8 @@ - int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, + } + } + +-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, ++/* Returns 1 if okfn() needs to be executed by the caller, ++ * -EPERM for NF_DROP, 0 otherwise. */ ++int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, struct net_device *indev, struct net_device *outdev, - int (*okfn)(struct sk_buff *)) @@ -7465,16 +5384,70 @@ diff -Nur linux-mips-cvs/net/core/netfilter.c linux-ebtables/net/core/netfilter. { struct list_head *elem; unsigned int verdict; -@@ -481,7 +504,7 @@ + int ret = 0; + + /* This stopgap cannot be removed until all the hooks are audited. */ +- if (skb_is_nonlinear(skb) && skb_linearize(skb, GFP_ATOMIC) != 0) { +- kfree_skb(skb); ++ if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) { ++ kfree_skb(*pskb); + return -ENOMEM; + } +- if (skb->ip_summed == CHECKSUM_HW) { ++ if ((*pskb)->ip_summed == CHECKSUM_HW) { + if (outdev == NULL) { +- skb->ip_summed = CHECKSUM_NONE; ++ (*pskb)->ip_summed = CHECKSUM_NONE; + } else { +- skb_checksum_help(skb); ++ skb_checksum_help(*pskb); + } + } + +@@ -472,30 +489,24 @@ int nf_hook_slow(int pf, unsigned int ho + br_read_lock_bh(BR_NETPROTO_LOCK); + + #ifdef CONFIG_NETFILTER_DEBUG +- if (skb->nf_debug & (1 << hook)) { ++ if (unlikely((*pskb)->nf_debug & (1 << hook))) { + printk("nf_hook: hook %i already set.\n", hook); +- nf_dump_skb(pf, skb); ++ nf_dump_skb(pf, *pskb); + } +- skb->nf_debug |= (1 << hook); ++ (*pskb)->nf_debug |= (1 << hook); + #endif elem = &nf_hooks[pf][hook]; - verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev, +- verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev, - outdev, &elem, okfn); +- if (verdict == NF_QUEUE) { +- NFDEBUG("nf_hook: Verdict = QUEUE.\n"); +- nf_queue(skb, elem, pf, hook, indev, outdev, okfn); +- } +- +- switch (verdict) { +- case NF_ACCEPT: +- ret = okfn(skb); +- break; +- +- case NF_DROP: +- kfree_skb(skb); ++ verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev, + outdev, &elem, okfn, hook_thresh); - if (verdict == NF_QUEUE) { - NFDEBUG("nf_hook: Verdict = QUEUE.\n"); - nf_queue(skb, elem, pf, hook, indev, outdev, okfn); -@@ -510,6 +533,14 @@ ++ if (verdict == NF_ACCEPT || verdict == NF_STOP) ++ ret = 1; ++ else if (verdict == NF_DROP) { ++ kfree_skb(*pskb); + ret = -EPERM; +- break; ++ } else if (verdict == NF_QUEUE) { ++ NFDEBUG("nf_hook: Verdict = QUEUE.\n"); ++ nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn); + } + + br_read_unlock_bh(BR_NETPROTO_LOCK); +@@ -510,6 +521,14 @@ void nf_reinject(struct sk_buff *skb, st /* We don't have BR_NETPROTO_LOCK here */ br_read_lock_bh(BR_NETPROTO_LOCK); @@ -7489,7 +5462,7 @@ diff -Nur linux-mips-cvs/net/core/netfilter.c linux-ebtables/net/core/netfilter. for (i = nf_hooks[info->pf][info->hook].next; i != elem; i = i->next) { if (i == &nf_hooks[info->pf][info->hook]) { /* The module which sent it to userspace is gone. */ -@@ -530,7 +561,7 @@ +@@ -530,7 +549,7 @@ void nf_reinject(struct sk_buff *skb, st verdict = nf_iterate(&nf_hooks[info->pf][info->hook], &skb, info->hook, info->indev, info->outdev, &elem, @@ -7498,10 +5471,9 @@ diff -Nur linux-mips-cvs/net/core/netfilter.c linux-ebtables/net/core/netfilter. } switch (verdict) { -diff -Nur linux-mips-cvs/net/core/skbuff.c linux-ebtables/net/core/skbuff.c ---- linux-mips-cvs/net/core/skbuff.c 2003-08-13 19:19:30.000000000 +0200 -+++ linux-ebtables/net/core/skbuff.c 2005-02-07 05:52:50.000000000 +0100 -@@ -246,6 +246,9 @@ +--- linux-2.4.29/net/core/skbuff.c 2003-08-25 13:44:44.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/net/core/skbuff.c 2005-03-14 00:00:30.000000000 +0100 +@@ -246,6 +246,9 @@ static inline void skb_headerinit(void * #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 0; #endif @@ -7511,7 +5483,7 @@ diff -Nur linux-mips-cvs/net/core/skbuff.c linux-ebtables/net/core/skbuff.c #endif #ifdef CONFIG_NET_SCHED skb->tc_index = 0; -@@ -326,6 +329,9 @@ +@@ -326,6 +329,9 @@ void __kfree_skb(struct sk_buff *skb) } #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); @@ -7521,7 +5493,7 @@ diff -Nur linux-mips-cvs/net/core/skbuff.c linux-ebtables/net/core/skbuff.c #endif skb_headerinit(skb, NULL, 0); /* clean state */ kfree_skbmem(skb); -@@ -393,6 +399,9 @@ +@@ -393,6 +399,9 @@ struct sk_buff *skb_clone(struct sk_buff #ifdef CONFIG_NETFILTER_DEBUG C(nf_debug); #endif @@ -7531,7 +5503,7 @@ diff -Nur linux-mips-cvs/net/core/skbuff.c linux-ebtables/net/core/skbuff.c #endif /*CONFIG_NETFILTER*/ #if defined(CONFIG_HIPPI) C(private); -@@ -405,6 +414,9 @@ +@@ -405,6 +414,9 @@ struct sk_buff *skb_clone(struct sk_buff skb->cloned = 1; #ifdef CONFIG_NETFILTER nf_conntrack_get(skb->nfct); @@ -7541,7 +5513,7 @@ diff -Nur linux-mips-cvs/net/core/skbuff.c linux-ebtables/net/core/skbuff.c #endif return n; } -@@ -440,6 +452,10 @@ +@@ -440,6 +452,10 @@ static void copy_skb_header(struct sk_bu #ifdef CONFIG_NETFILTER_DEBUG new->nf_debug=old->nf_debug; #endif @@ -7552,7 +5524,7 @@ diff -Nur linux-mips-cvs/net/core/skbuff.c linux-ebtables/net/core/skbuff.c #endif #ifdef CONFIG_NET_SCHED new->tc_index = old->tc_index; -@@ -726,9 +742,9 @@ +@@ -726,9 +742,9 @@ struct sk_buff *skb_copy_expand(const st /* Set the tail pointer and length */ skb_put(n,skb->len); @@ -7565,10 +5537,106 @@ diff -Nur linux-mips-cvs/net/core/skbuff.c linux-ebtables/net/core/skbuff.c copy_skb_header(n, skb); return n; -diff -Nur linux-mips-cvs/net/ipv4/ip_output.c linux-ebtables/net/ipv4/ip_output.c ---- linux-mips-cvs/net/ipv4/ip_output.c 2005-01-20 03:19:25.000000000 +0100 -+++ linux-ebtables/net/ipv4/ip_output.c 2005-02-07 05:52:50.000000000 +0100 -@@ -890,6 +890,10 @@ +--- linux-2.4.29/net/ipv4/netfilter/ip_tables.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/ipv4/netfilter/ip_tables.c 2005-03-14 00:00:30.000000000 +0100 +@@ -118,12 +118,19 @@ static LIST_HEAD(ipt_tables); + static inline int + ip_packet_match(const struct iphdr *ip, + const char *indev, ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ const char *physindev, ++#endif + const char *outdev, ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ const char *physoutdev, ++#endif + const struct ipt_ip *ipinfo, + int isfrag) + { + size_t i; + unsigned long ret; ++ unsigned long ret2 = 1; + + #define FWINV(bool,invflg) ((bool) ^ !!(ipinfo->invflags & invflg)) + +@@ -153,7 +160,15 @@ ip_packet_match(const struct iphdr *ip, + & ((const unsigned long *)ipinfo->iniface_mask)[i]; + } + +- if (FWINV(ret != 0, IPT_INV_VIA_IN)) { ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ for (i = 0, ret2 = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { ++ ret2 |= (((const unsigned long *)physindev)[i] ++ ^ ((const unsigned long *)ipinfo->iniface)[i]) ++ & ((const unsigned long *)ipinfo->iniface_mask)[i]; ++ } ++#endif ++ ++ if (FWINV(ret != 0 && ret2 != 0, IPT_INV_VIA_IN)) { + dprintf("VIA in mismatch (%s vs %s).%s\n", + indev, ipinfo->iniface, + ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":""); +@@ -166,7 +181,15 @@ ip_packet_match(const struct iphdr *ip, + & ((const unsigned long *)ipinfo->outiface_mask)[i]; + } + +- if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ for (i = 0, ret2 = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { ++ ret2 |= (((const unsigned long *)physoutdev)[i] ++ ^ ((const unsigned long *)ipinfo->outiface)[i]) ++ & ((const unsigned long *)ipinfo->outiface_mask)[i]; ++ } ++#endif ++ ++ if (FWINV(ret != 0 && ret2 != 0, IPT_INV_VIA_OUT)) { + dprintf("VIA out mismatch (%s vs %s).%s\n", + outdev, ipinfo->outiface, + ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":""); +@@ -265,6 +288,9 @@ ipt_do_table(struct sk_buff **pskb, + /* Initializing verdict to NF_DROP keeps gcc happy. */ + unsigned int verdict = NF_DROP; + const char *indev, *outdev; ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ const char *physindev, *physoutdev; ++#endif + void *table_base; + struct ipt_entry *e, *back; + +@@ -274,6 +300,13 @@ ipt_do_table(struct sk_buff **pskb, + datalen = (*pskb)->len - ip->ihl * 4; + indev = in ? in->name : nulldevname; + outdev = out ? out->name : nulldevname; ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ physindev = ((*pskb)->nf_bridge && (*pskb)->nf_bridge->physindev) ? ++ (*pskb)->nf_bridge->physindev->name : nulldevname; ++ physoutdev = ((*pskb)->nf_bridge && (*pskb)->nf_bridge->physoutdev) ? ++ (*pskb)->nf_bridge->physoutdev->name : nulldevname; ++#endif ++ + /* We handle fragments by dealing with the first fragment as + * if it was a normal packet. All other fragments are treated + * normally, except that they will NEVER match rules that ask +@@ -309,7 +342,15 @@ ipt_do_table(struct sk_buff **pskb, + IP_NF_ASSERT(e); + IP_NF_ASSERT(back); + (*pskb)->nfcache |= e->nfcache; +- if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) { ++ if (ip_packet_match(ip, indev, ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ physindev, ++#endif ++ outdev, ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ physoutdev, ++#endif ++ &e->ip, offset)) { + struct ipt_entry_target *t; + + if (IPT_MATCH_ITERATE(e, do_match, +--- linux-2.4.29/net/ipv4/ip_output.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/ipv4/ip_output.c 2005-03-14 00:00:30.000000000 +0100 +@@ -890,6 +890,10 @@ int ip_fragment(struct sk_buff *skb, int /* Connection association is same as pre-frag packet */ skb2->nfct = skb->nfct; nf_conntrack_get(skb2->nfct); @@ -7579,1652 +5647,1156 @@ diff -Nur linux-mips-cvs/net/ipv4/ip_output.c linux-ebtables/net/ipv4/ip_output. #ifdef CONFIG_NETFILTER_DEBUG skb2->nf_debug = skb->nf_debug; #endif -diff -Nur linux-mips-cvs/net/ipv4/ip_output.c.orig linux-ebtables/net/ipv4/ip_output.c.orig ---- linux-mips-cvs/net/ipv4/ip_output.c.orig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/ipv4/ip_output.c.orig 2005-01-20 03:19:25.000000000 +0100 -@@ -0,0 +1,1036 @@ +--- linux-2.4.29/net/ipv4/netfilter/ipt_LOG.c 2003-11-28 19:26:21.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/ipv4/netfilter/ipt_LOG.c 2005-03-14 00:00:30.000000000 +0100 +@@ -316,6 +316,18 @@ ipt_log_target(struct sk_buff **pskb, + loginfo->prefix, + in ? in->name : "", + out ? out->name : ""); ++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) ++ if ((*pskb)->nf_bridge) { ++ struct net_device *physindev = (*pskb)->nf_bridge->physindev; ++ struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev; ++ ++ if (physindev && in != physindev) ++ printk("PHYSIN=%s ", physindev->name); ++ if (physoutdev && out != physoutdev) ++ printk("PHYSOUT=%s ", physoutdev->name); ++ } ++#endif ++ + if (in && !out) { + /* MAC logging for input chain only. */ + printk("MAC="); +--- linux-2.4.29/net/ipv4/netfilter/Makefile 2003-08-25 13:44:44.000000000 +0200 ++++ linux-2.4.29-ebt-brnf/net/ipv4/netfilter/Makefile 2005-03-14 00:00:30.000000000 +0100 +@@ -87,6 +87,8 @@ obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += i + obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o + obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o + ++obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o ++ + # targets + obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o + obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o +--- linux-2.4.29/net/ipv4/netfilter/Config.in 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/ipv4/netfilter/Config.in 2005-03-14 00:00:30.000000000 +0100 +@@ -44,6 +44,9 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; + dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES + dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES + fi ++ if [ "$CONFIG_BRIDGE" != "n" ]; then ++ dep_tristate ' Physdev match support' CONFIG_IP_NF_MATCH_PHYSDEV $CONFIG_IP_NF_IPTABLES ++ fi + # The targets + dep_tristate ' Packet filtering' CONFIG_IP_NF_FILTER $CONFIG_IP_NF_IPTABLES + if [ "$CONFIG_IP_NF_FILTER" != "n" ]; then +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/bridge/br_netfilter.c 2005-03-14 00:00:30.000000000 +0100 +@@ -0,0 +1,1101 @@ +/* -+ * INET An implementation of the TCP/IP protocol suite for the LINUX -+ * operating system. INET is implemented using the BSD Socket -+ * interface as the means of communication with the user level. -+ * -+ * The Internet Protocol (IP) output module. ++ * Handle firewalling ++ * Linux ethernet bridge + * -+ * Version: $Id$ ++ * Authors: ++ * Lennert Buytenhek <buytenh@gnu.org> ++ * Bart De Schuymer (maintainer) <bdschuym@pandora.be> + * -+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu> -+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> -+ * Donald Becker, <becker@super.org> -+ * Alan Cox, <Alan.Cox@linux.org> -+ * Richard Underwood -+ * Stefan Becker, <stefanb@yello.ping.de> -+ * Jorge Cwik, <jorge@laser.satlink.net> -+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no> ++ * Changes: ++ * Apr 29 2003: physdev module support (bdschuym) ++ * Jun 19 2003: let arptables see bridged ARP traffic (bdschuym) ++ * Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge ++ * (bdschuym) ++ * Aug 28 2004: add IPv6 filtering (bdschuym) + * -+ * See ip_input.c for original log ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. + * -+ * Fixes: -+ * Alan Cox : Missing nonblock feature in ip_build_xmit. -+ * Mike Kilburn : htons() missing in ip_build_xmit. -+ * Bradford Johnson: Fix faulty handling of some frames when -+ * no route is found. -+ * Alexander Demenshin: Missing sk/skb free in ip_queue_xmit -+ * (in case if packet not accepted by -+ * output firewall rules) -+ * Mike McLagan : Routing by source -+ * Alexey Kuznetsov: use new route cache -+ * Andi Kleen: Fix broken PMTU recovery and remove -+ * some redundant tests. -+ * Vitaly E. Lavrov : Transparent proxy revived after year coma. -+ * Andi Kleen : Replace ip_reply with ip_send_reply. -+ * Andi Kleen : Split fast and slow ip_build_xmit path -+ * for decreased register pressure on x86 -+ * and more readibility. -+ * Marc Boucher : When call_out_firewall returns FW_QUEUE, -+ * silently drop skb instead of failing with -EPERM. -+ * Detlev Wengorz : Copy protocol for fragments. ++ * Lennert dedicates this file to Kerstin Wurdinger. + */ + -+#include <asm/uaccess.h> -+#include <asm/system.h> -+#include <linux/types.h> ++#include <linux/module.h> +#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <linux/string.h> -+#include <linux/errno.h> -+#include <linux/config.h> -+ -+#include <linux/socket.h> -+#include <linux/sockios.h> -+#include <linux/in.h> -+#include <linux/inet.h> ++#include <linux/ip.h> +#include <linux/netdevice.h> -+#include <linux/etherdevice.h> -+#include <linux/proc_fs.h> -+#include <linux/stat.h> -+#include <linux/init.h> -+ -+#include <net/snmp.h> -+#include <net/ip.h> -+#include <net/protocol.h> -+#include <net/route.h> -+#include <net/tcp.h> -+#include <net/udp.h> +#include <linux/skbuff.h> -+#include <net/sock.h> -+#include <net/arp.h> -+#include <net/icmp.h> -+#include <net/raw.h> -+#include <net/checksum.h> -+#include <net/inetpeer.h> -+#include <linux/igmp.h> ++#include <linux/if_ether.h> ++#include <linux/if_vlan.h> ++#include <linux/netfilter_bridge.h> +#include <linux/netfilter_ipv4.h> -+#include <linux/mroute.h> -+#include <linux/netlink.h> -+ -+/* -+ * Shall we try to damage output packets if routing dev changes? -+ */ -+ -+int sysctl_ip_dynaddr = 0; -+int sysctl_ip_default_ttl = IPDEFTTL; ++#include <linux/netfilter_ipv6.h> ++#include <linux/in_route.h> ++#include <net/ip.h> ++#include <net/ipv6.h> ++#include <asm/uaccess.h> ++#include <asm/checksum.h> ++#include "br_private.h" ++#ifdef CONFIG_SYSCTL ++#include <linux/sysctl.h> ++#endif + -+/* Generate a checksum for an outgoing IP datagram. */ -+__inline__ void ip_send_check(struct iphdr *iph) -+{ -+ iph->check = 0; -+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); -+} ++#define skb_origaddr(skb) (((struct bridge_skb_cb *) \ ++ (skb->nf_bridge->data))->daddr.ipv4) ++#define store_orig_dstaddr(skb) (skb_origaddr(skb) = (skb)->nh.iph->daddr) ++#define dnat_took_place(skb) (skb_origaddr(skb) != (skb)->nh.iph->daddr) + -+/* dev_loopback_xmit for use with netfilter. */ -+static int ip_dev_loopback_xmit(struct sk_buff *newskb) -+{ -+ newskb->mac.raw = newskb->data; -+ __skb_pull(newskb, newskb->nh.raw - newskb->data); -+ newskb->pkt_type = PACKET_LOOPBACK; -+ newskb->ip_summed = CHECKSUM_UNNECESSARY; -+ BUG_TRAP(newskb->dst); ++#define has_bridge_parent(device) ((device)->br_port != NULL) ++#define bridge_parent(device) (&((device)->br_port->br->dev)) + -+#ifdef CONFIG_NETFILTER_DEBUG -+ nf_debug_ip_loopback_xmit(newskb); ++#ifdef CONFIG_SYSCTL ++static struct ctl_table_header *brnf_sysctl_header; ++static int brnf_call_iptables = 1; ++static int brnf_call_ip6tables = 1; ++static int brnf_call_arptables = 1; ++static int brnf_filter_vlan_tagged = 1; ++#else ++#define brnf_filter_vlan_tagged 1 +#endif -+ netif_rx(newskb); -+ return 0; -+} + -+/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook -+ changes route */ -+static inline int -+output_maybe_reroute(struct sk_buff *skb) -+{ -+ return skb->dst->output(skb); -+} ++#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ ++ hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) && \ ++ brnf_filter_vlan_tagged) ++#define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) && \ ++ hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) && \ ++ brnf_filter_vlan_tagged) ++/* ++#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ ++ hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \ ++ brnf_filter_vlan_tagged) ++*/ + -+/* -+ * Add an ip header to a skbuff and send it out. ++/* We need these fake structures to make netfilter happy -- ++ * lots of places assume that skb->dst != NULL, which isn't ++ * all that unreasonable. ++ * ++ * Currently, we fill in the PMTU entry because netfilter ++ * refragmentation needs it, and the rt_flags entry because ++ * ipt_REJECT needs it. Future netfilter modules might ++ * require us to fill additional fields. + */ -+int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, -+ u32 saddr, u32 daddr, struct ip_options *opt) -+{ -+ struct rtable *rt = (struct rtable *)skb->dst; -+ struct iphdr *iph; -+ -+ /* Build the IP header. */ -+ if (opt) -+ iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr) + opt->optlen); -+ else -+ iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr)); ++static struct net_device __fake_net_device = { ++ .hard_header_len = ETH_HLEN ++}; + -+ iph->version = 4; -+ iph->ihl = 5; -+ iph->tos = sk->protinfo.af_inet.tos; -+ if (ip_dont_fragment(sk, &rt->u.dst)) -+ iph->frag_off = htons(IP_DF); -+ else -+ iph->frag_off = 0; -+ iph->ttl = sk->protinfo.af_inet.ttl; -+ iph->daddr = rt->rt_dst; -+ iph->saddr = rt->rt_src; -+ iph->protocol = sk->protocol; -+ iph->tot_len = htons(skb->len); -+ ip_select_ident(iph, &rt->u.dst, sk); -+ skb->nh.iph = iph; ++static struct rtable __fake_rtable = { ++ u: { ++ dst: { ++ __refcnt: ATOMIC_INIT(1), ++ dev: &__fake_net_device, ++ pmtu: 1500 ++ } ++ }, + -+ if (opt && opt->optlen) { -+ iph->ihl += opt->optlen>>2; -+ ip_options_build(skb, opt, daddr, rt, 0); -+ } -+ ip_send_check(iph); ++ rt_flags: 0 ++}; + -+ /* Send it out. */ -+ return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, -+ output_maybe_reroute); -+} + -+static inline int ip_finish_output2(struct sk_buff *skb) ++/* PF_BRIDGE/PRE_ROUTING *********************************************/ ++/* Undo the changes made for ip6tables PREROUTING and continue the ++ * bridge PRE_ROUTING hook. */ ++static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) +{ -+ struct dst_entry *dst = skb->dst; -+ struct hh_cache *hh = dst->hh; ++ struct nf_bridge_info *nf_bridge = skb->nf_bridge; + +#ifdef CONFIG_NETFILTER_DEBUG -+ nf_debug_ip_finish_output2(skb); -+#endif /*CONFIG_NETFILTER_DEBUG*/ ++ skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING); ++#endif + -+ if (hh) { -+ int hh_alen; ++ if (nf_bridge->mask & BRNF_PKT_TYPE) { ++ skb->pkt_type = PACKET_OTHERHOST; ++ nf_bridge->mask ^= BRNF_PKT_TYPE; ++ } ++ nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; ++ ++ skb->dst = (struct dst_entry *)&__fake_rtable; ++ dst_hold(skb->dst); + -+ read_lock_bh(&hh->hh_lock); -+ hh_alen = HH_DATA_ALIGN(hh->hh_len); -+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); -+ read_unlock_bh(&hh->hh_lock); -+ skb_push(skb, hh->hh_len); -+ return hh->hh_output(skb); -+ } else if (dst->neighbour) -+ return dst->neighbour->output(skb); ++ skb->dev = nf_bridge->physindev; ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_push(skb, VLAN_HLEN); ++ skb->nh.raw -= VLAN_HLEN; ++ } ++ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, ++ br_handle_frame_finish, 1); + -+ if (net_ratelimit()) -+ printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n"); -+ kfree_skb(skb); -+ return -EINVAL; ++ return 0; +} + -+static __inline__ int __ip_finish_output(struct sk_buff *skb) ++static void __br_dnat_complain(void) +{ -+ struct net_device *dev = skb->dst->dev; -+ -+ skb->dev = dev; -+ skb->protocol = htons(ETH_P_IP); ++ static unsigned long last_complaint; + -+ return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, -+ ip_finish_output2); ++ if (jiffies - last_complaint >= 5 * HZ) { ++ printk(KERN_WARNING "Performing cross-bridge DNAT requires IP " ++ "forwarding to be enabled\n"); ++ last_complaint = jiffies; ++ } +} + -+int ip_finish_output(struct sk_buff *skb) -+{ -+ return __ip_finish_output(skb); -+} + -+int ip_mc_output(struct sk_buff *skb) -+{ -+ struct sock *sk = skb->sk; -+ struct rtable *rt = (struct rtable*)skb->dst; -+ struct net_device *dev = rt->u.dst.dev; ++/* This requires some explaining. If DNAT has taken place, ++ * we will need to fix up the destination Ethernet address, ++ * and this is a tricky process. ++ * ++ * There are two cases to consider: ++ * 1. The packet was DNAT'ed to a device in the same bridge ++ * port group as it was received on. We can still bridge ++ * the packet. ++ * 2. The packet was DNAT'ed to a different device, either ++ * a non-bridged device or another bridge port group. ++ * The packet will need to be routed. ++ * ++ * The correct way of distinguishing between these two cases is to ++ * call ip_route_input() and to look at skb->dst->dev, which is ++ * changed to the destination device if ip_route_input() succeeds. ++ * ++ * Let us first consider the case that ip_route_input() succeeds: ++ * ++ * If skb->dst->dev equals the logical bridge device the packet ++ * came in on, we can consider this bridging. We then call ++ * skb->dst->output() which will make the packet enter br_nf_local_out() ++ * not much later. In that function it is assured that the iptables ++ * FORWARD chain is traversed for the packet. ++ * ++ * Otherwise, the packet is considered to be routed and we just ++ * change the destination MAC address so that the packet will ++ * later be passed up to the IP stack to be routed. ++ * ++ * Let us now consider the case that ip_route_input() fails: ++ * ++ * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input() ++ * will fail, while __ip_route_output_key() will return success. The source ++ * address for __ip_route_output_key() is set to zero, so __ip_route_output_key ++ * thinks we're handling a locally generated packet and won't care ++ * if IP forwarding is allowed. We send a warning message to the users's ++ * log telling her to put IP forwarding on. ++ * ++ * ip_route_input() will also fail if there is no route available. ++ * In that case we just drop the packet. ++ * ++ * --Lennert, 20020411 ++ * --Bart, 20020416 (updated) ++ * --Bart, 20021007 (updated) ++ */ + -+ /* -+ * If the indicated interface is up and running, send the packet. -+ */ -+ IP_INC_STATS(IpOutRequests); -+#ifdef CONFIG_IP_ROUTE_NAT -+ if (rt->rt_flags & RTCF_NAT) -+ ip_do_nat(skb); ++static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) ++{ ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug |= (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_FORWARD); +#endif + -+ skb->dev = dev; -+ skb->protocol = htons(ETH_P_IP); ++ if (skb->pkt_type == PACKET_OTHERHOST) { ++ skb->pkt_type = PACKET_HOST; ++ skb->nf_bridge->mask |= BRNF_PKT_TYPE; ++ } ++ skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; + -+ /* -+ * Multicasts are looped back for other local users -+ */ ++ skb->dev = bridge_parent(skb->dev); ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_pull(skb, VLAN_HLEN); ++ skb->nh.raw += VLAN_HLEN; ++ } ++ skb->dst->output(skb); ++ return 0; ++} + -+ if (rt->rt_flags&RTCF_MULTICAST) { -+ if ((!sk || sk->protinfo.af_inet.mc_loop) -+#ifdef CONFIG_IP_MROUTE -+ /* Small optimization: do not loopback not local frames, -+ which returned after forwarding; they will be dropped -+ by ip_mr_input in any case. -+ Note, that local frames are looped back to be delivered -+ to local recipients. ++static int br_nf_pre_routing_finish(struct sk_buff *skb) ++{ ++ struct net_device *dev = skb->dev; ++ struct iphdr *iph = skb->nh.iph; ++ struct nf_bridge_info *nf_bridge = skb->nf_bridge; + -+ This check is duplicated in ip_mr_input at the moment. -+ */ -+ && ((rt->rt_flags&RTCF_LOCAL) || !(IPCB(skb)->flags&IPSKB_FORWARDED)) ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING); +#endif -+ ) { -+ struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); -+ if (newskb) -+ NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL, -+ newskb->dev, -+ ip_dev_loopback_xmit); -+ } + -+ /* Multicasts with ttl 0 must not go beyond the host */ ++ if (nf_bridge->mask & BRNF_PKT_TYPE) { ++ skb->pkt_type = PACKET_OTHERHOST; ++ nf_bridge->mask ^= BRNF_PKT_TYPE; ++ } ++ nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; ++ ++ if (dnat_took_place(skb)) { ++ if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, ++ dev)) { ++ struct rtable *rt; + -+ if (skb->nh.iph->ttl == 0) { ++ if (!ip_route_output(&rt, iph->daddr, 0, iph->tos, 0)) { ++ /* Bridged-and-DNAT'ed traffic doesn't ++ * require ip_forwarding. ++ */ ++ if (((struct dst_entry *)rt)->dev == dev) { ++ skb->dst = (struct dst_entry *)rt; ++ goto bridged_dnat; ++ } ++ __br_dnat_complain(); ++ dst_release((struct dst_entry *)rt); ++ } + kfree_skb(skb); + return 0; ++ } else { ++ if (skb->dst->dev == dev) { ++bridged_dnat: ++ /* Tell br_nf_local_out this is a ++ * bridged frame ++ */ ++ nf_bridge->mask |= BRNF_BRIDGED_DNAT; ++ skb->dev = nf_bridge->physindev; ++ if (skb->protocol == ++ __constant_htons(ETH_P_8021Q)) { ++ skb_push(skb, VLAN_HLEN); ++ skb->nh.raw -= VLAN_HLEN; ++ } ++ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, ++ skb, skb->dev, NULL, ++ br_nf_pre_routing_finish_bridge, ++ 1); ++ return 0; ++ } ++ memcpy(skb->mac.ethernet->h_dest, dev->dev_addr, ++ ETH_ALEN); ++ skb->pkt_type = PACKET_HOST; + } ++ } else { ++ skb->dst = (struct dst_entry *)&__fake_rtable; ++ dst_hold(skb->dst); + } + -+ if (rt->rt_flags&RTCF_BROADCAST) { -+ struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); -+ if (newskb) -+ NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL, -+ newskb->dev, ip_dev_loopback_xmit); ++ skb->dev = nf_bridge->physindev; ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_push(skb, VLAN_HLEN); ++ skb->nh.raw -= VLAN_HLEN; + } ++ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, ++ br_handle_frame_finish, 1); + -+ return __ip_finish_output(skb); ++ return 0; +} + -+int ip_output(struct sk_buff *skb) ++/* Some common code for IPv4/IPv6 */ ++static void setup_pre_routing(struct sk_buff *skb) +{ -+#ifdef CONFIG_IP_ROUTE_NAT -+ struct rtable *rt = (struct rtable*)skb->dst; -+#endif -+ -+ IP_INC_STATS(IpOutRequests); ++ struct nf_bridge_info *nf_bridge = skb->nf_bridge; + -+#ifdef CONFIG_IP_ROUTE_NAT -+ if (rt->rt_flags&RTCF_NAT) -+ ip_do_nat(skb); -+#endif ++ if (skb->pkt_type == PACKET_OTHERHOST) { ++ skb->pkt_type = PACKET_HOST; ++ nf_bridge->mask |= BRNF_PKT_TYPE; ++ } + -+ return __ip_finish_output(skb); ++ nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; ++ nf_bridge->physindev = skb->dev; ++ skb->dev = bridge_parent(skb->dev); +} + -+/* Queues a packet to be sent, and starts the transmitter if necessary. -+ * This routine also needs to put in the total length and compute the -+ * checksum. We use to do this in two stages, ip_build_header() then -+ * this, but that scheme created a mess when routes disappeared etc. -+ * So we do it all here, and the TCP send engine has been changed to -+ * match. (No more unroutable FIN disasters, etc. wheee...) This will -+ * most likely make other reliable transport layers above IP easier -+ * to implement under Linux. -+ */ -+static inline int ip_queue_xmit2(struct sk_buff *skb) ++/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */ ++static int check_hbh_len(struct sk_buff *skb) +{ -+ struct sock *sk = skb->sk; -+ struct rtable *rt = (struct rtable *)skb->dst; -+ struct net_device *dev; -+ struct iphdr *iph = skb->nh.iph; -+ -+ dev = rt->u.dst.dev; ++ unsigned char *raw = (u8*)(skb->nh.ipv6h+1); ++ u32 pkt_len; ++ int off = raw - skb->nh.raw; ++ int len = (raw[1]+1)<<3; + -+ /* This can happen when the transport layer has segments queued -+ * with a cached route, and by the time we get here things are -+ * re-routed to a device with a different MTU than the original -+ * device. Sick, but we must cover it. -+ */ -+ if (skb_headroom(skb) < dev->hard_header_len && dev->hard_header) { -+ struct sk_buff *skb2; ++ if ((raw + len) - skb->data > skb_headlen(skb)) ++ goto bad; + -+ skb2 = skb_realloc_headroom(skb, (dev->hard_header_len + 15) & ~15); -+ kfree_skb(skb); -+ if (skb2 == NULL) -+ return -ENOMEM; -+ if (sk) -+ skb_set_owner_w(skb2, sk); -+ skb = skb2; -+ iph = skb->nh.iph; -+ } ++ off += 2; ++ len -= 2; + -+ if (skb->len > rt->u.dst.pmtu) -+ goto fragment; ++ while (len > 0) { ++ int optlen = raw[off+1]+2; + -+ ip_select_ident(iph, &rt->u.dst, sk); ++ switch (skb->nh.raw[off]) { ++ case IPV6_TLV_PAD0: ++ optlen = 1; ++ break; + -+ /* Add an IP checksum. */ -+ ip_send_check(iph); ++ case IPV6_TLV_PADN: ++ break; + -+ skb->priority = sk->priority; -+ return skb->dst->output(skb); ++ case IPV6_TLV_JUMBO: ++ if (skb->nh.raw[off+1] != 4 || (off&3) != 2) ++ goto bad; + -+fragment: -+ if (ip_dont_fragment(sk, &rt->u.dst)) { -+ /* Reject packet ONLY if TCP might fragment -+ * it itself, if were careful enough. -+ */ -+ NETDEBUG(printk(KERN_DEBUG "sending pkt_too_big (len[%u] pmtu[%u]) to self\n", -+ skb->len, rt->u.dst.pmtu)); ++ pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2)); + -+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, -+ htonl(rt->u.dst.pmtu)); -+ kfree_skb(skb); -+ return -EMSGSIZE; ++ if (pkt_len > skb->len - sizeof(struct ipv6hdr)) ++ goto bad; ++ if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { ++ if (__pskb_trim(skb, ++ pkt_len + sizeof(struct ipv6hdr))) ++ goto bad; ++ if (skb->ip_summed == CHECKSUM_HW) ++ skb->ip_summed = CHECKSUM_NONE; ++ } ++ break; ++ default: ++ if (optlen > len) ++ goto bad; ++ break; ++ } ++ off += optlen; ++ len -= optlen; + } -+ ip_select_ident(iph, &rt->u.dst, sk); -+ if (skb->ip_summed == CHECKSUM_HW && -+ (skb = skb_checksum_help(skb)) == NULL) -+ return -ENOMEM; -+ return ip_fragment(skb, skb->dst->output); ++ if (len == 0) ++ return 0; ++bad: ++ return -1; ++ +} + -+int ip_queue_xmit(struct sk_buff *skb, int ipfragok) ++/* Replicate the checks that IPv6 does on packet reception and pass the packet ++ * to ip6tables, which doesn't support NAT, so things are fairly simple. */ ++static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, ++ struct sk_buff *skb, const struct net_device *in, ++ const struct net_device *out, int (*okfn)(struct sk_buff *)) +{ -+ struct sock *sk = skb->sk; -+ struct ip_options *opt = sk->protinfo.af_inet.opt; -+ struct rtable *rt; -+ struct iphdr *iph; -+ -+ /* Skip all of this if the packet is already routed, -+ * f.e. by something like SCTP. -+ */ -+ rt = (struct rtable *) skb->dst; -+ if (rt != NULL) -+ goto packet_routed; -+ -+ /* Make sure we can route this packet. */ -+ rt = (struct rtable *)__sk_dst_check(sk, 0); -+ if (rt == NULL) { -+ u32 daddr; -+ -+ /* Use correct destination address if we have options. */ -+ daddr = sk->daddr; -+ if(opt && opt->srr) -+ daddr = opt->faddr; -+ -+ /* If this fails, retransmit mechanism of transport layer will -+ * keep trying until route appears or the connection times itself -+ * out. -+ */ -+ if (ip_route_output(&rt, daddr, sk->saddr, -+ RT_CONN_FLAGS(sk), -+ sk->bound_dev_if)) -+ goto no_route; -+ __sk_dst_set(sk, &rt->u.dst); -+ sk->route_caps = rt->u.dst.dev->features; -+ } -+ skb->dst = dst_clone(&rt->u.dst); -+ -+packet_routed: -+ if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) -+ goto no_route; -+ -+ /* OK, we know where to send it, allocate and build IP header. */ -+ iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); -+ *((__u16 *)iph) = htons((4 << 12) | (5 << 8) | (sk->protinfo.af_inet.tos & 0xff)); -+ iph->tot_len = htons(skb->len); -+ if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok) -+ iph->frag_off = htons(IP_DF); -+ else -+ iph->frag_off = 0; -+ iph->ttl = sk->protinfo.af_inet.ttl; -+ iph->protocol = sk->protocol; -+ iph->saddr = rt->rt_src; -+ iph->daddr = rt->rt_dst; -+ skb->nh.iph = iph; -+ /* Transport layer set skb->h.foo itself. */ ++ struct ipv6hdr *hdr; ++ u32 pkt_len; ++ struct nf_bridge_info *nf_bridge; + -+ if(opt && opt->optlen) { -+ iph->ihl += opt->optlen >> 2; -+ ip_options_build(skb, opt, sk->daddr, rt, 0); -+ } ++ if (skb->len < sizeof(struct ipv6hdr)) ++ goto inhdr_error; + -+ return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, -+ ip_queue_xmit2); ++ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) ++ goto inhdr_error; + -+no_route: -+ IP_INC_STATS(IpOutNoRoutes); -+ kfree_skb(skb); -+ return -EHOSTUNREACH; -+} ++ hdr = skb->nh.ipv6h; + -+/* -+ * Build and send a packet, with as little as one copy -+ * -+ * Doesn't care much about ip options... option length can be -+ * different for fragment at 0 and other fragments. -+ * -+ * Note that the fragment at the highest offset is sent first, -+ * so the getfrag routine can fill in the TCP/UDP checksum header -+ * field in the last fragment it sends... actually it also helps -+ * the reassemblers, they can put most packets in at the head of -+ * the fragment queue, and they know the total size in advance. This -+ * last feature will measurably improve the Linux fragment handler one -+ * day. -+ * -+ * The callback has five args, an arbitrary pointer (copy of frag), -+ * the source IP address (may depend on the routing table), the -+ * destination address (char *), the offset to copy from, and the -+ * length to be copied. -+ */ ++ if (hdr->version != 6) ++ goto inhdr_error; + -+static int ip_build_xmit_slow(struct sock *sk, -+ int getfrag (const void *, -+ char *, -+ unsigned int, -+ unsigned int, -+ struct sk_buff *), -+ const void *frag, -+ unsigned length, -+ struct ipcm_cookie *ipc, -+ struct rtable *rt, -+ int flags) -+{ -+ unsigned int fraglen, maxfraglen, fragheaderlen; -+ int err; -+ int offset, mf; -+ int mtu; -+ u16 id; ++ pkt_len = ntohs(hdr->payload_len); + -+ int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15; -+ int nfrags=0; -+ struct ip_options *opt = ipc->opt; -+ int df = 0; ++ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { ++ if (pkt_len + sizeof(struct ipv6hdr) > skb->len) ++ goto inhdr_error; ++ if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { ++ if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))) ++ goto inhdr_error; ++ if (skb->ip_summed == CHECKSUM_HW) ++ skb->ip_summed = CHECKSUM_NONE; ++ } ++ } ++ if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) ++ goto inhdr_error; + -+ mtu = rt->u.dst.pmtu; -+ if (ip_dont_fragment(sk, &rt->u.dst)) -+ df = htons(IP_DF); ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING); ++#endif ++ if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) ++ return NF_DROP; ++ setup_pre_routing(skb); + -+ length -= sizeof(struct iphdr); ++ NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, ++ br_nf_pre_routing_finish_ipv6); + -+ if (opt) { -+ fragheaderlen = sizeof(struct iphdr) + opt->optlen; -+ maxfraglen = ((mtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen; -+ } else { -+ fragheaderlen = sizeof(struct iphdr); ++ return NF_STOLEN; + -+ /* -+ * Fragheaderlen is the size of 'overhead' on each buffer. Now work -+ * out the size of the frames to send. -+ */ ++inhdr_error: ++ return NF_DROP; ++} + -+ maxfraglen = ((mtu-sizeof(struct iphdr)) & ~7) + fragheaderlen; -+ } ++/* Direct IPv6 traffic to br_nf_pre_routing_ipv6. ++ * Replicate the checks that IPv4 does on packet reception. ++ * Set skb->dev to the bridge device (i.e. parent of the ++ * receiving device) to make netfilter happy, the REDIRECT ++ * target in particular. Save the original destination IP ++ * address to be able to detect DNAT afterwards. ++ */ ++static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) ++{ ++ struct iphdr *iph; ++ __u32 len; ++ struct sk_buff *skb = *pskb; ++ struct nf_bridge_info *nf_bridge; ++ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *) ++ ((*pskb)->mac.ethernet); ++ ++ if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) { ++#ifdef CONFIG_SYSCTL ++ if (!brnf_call_ip6tables) ++ return NF_ACCEPT; ++#endif ++ if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) ++ goto out; + -+ if (length + fragheaderlen > 0xFFFF) { -+ ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu); -+ return -EMSGSIZE; ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_pull(skb, VLAN_HLEN); ++ (skb)->nh.raw += VLAN_HLEN; ++ } ++ return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); + } + -+ /* -+ * Start at the end of the frame by handling the remainder. -+ */ -+ -+ offset = length - (length % (maxfraglen - fragheaderlen)); ++#ifdef CONFIG_SYSCTL ++ if (!brnf_call_iptables) ++ return NF_ACCEPT; ++#endif + -+ /* -+ * Amount of memory to allocate for final fragment. -+ */ ++ if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP) ++ return NF_ACCEPT; ++ if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) ++ goto out; ++ ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_pull(skb, VLAN_HLEN); ++ (skb)->nh.raw += VLAN_HLEN; ++ } + -+ fraglen = length - offset + fragheaderlen; ++ if (!pskb_may_pull(skb, sizeof(struct iphdr))) ++ goto inhdr_error; + -+ if (length-offset==0) { -+ fraglen = maxfraglen; -+ offset -= maxfraglen-fragheaderlen; -+ } ++ iph = skb->nh.iph; ++ if (iph->ihl < 5 || iph->version != 4) ++ goto inhdr_error; + -+ /* -+ * The last fragment will not have MF (more fragments) set. -+ */ ++ if (!pskb_may_pull(skb, 4*iph->ihl)) ++ goto inhdr_error; + -+ mf = 0; ++ iph = skb->nh.iph; ++ if (ip_fast_csum((__u8 *)iph, iph->ihl) != 0) ++ goto inhdr_error; + -+ /* -+ * Don't fragment packets for path mtu discovery. -+ */ ++ len = ntohs(iph->tot_len); ++ if (skb->len < len || len < 4*iph->ihl) ++ goto inhdr_error; + -+ if (offset > 0 && sk->protinfo.af_inet.pmtudisc==IP_PMTUDISC_DO) { -+ ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu); -+ return -EMSGSIZE; ++ if (skb->len > len) { ++ __pskb_trim(skb, len); ++ if (skb->ip_summed == CHECKSUM_HW) ++ skb->ip_summed = CHECKSUM_NONE; + } -+ if (flags&MSG_PROBE) -+ goto out; + -+ /* -+ * Begin outputting the bytes. -+ */ ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING); ++#endif ++ if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) ++ return NF_DROP; + -+ id = sk->protinfo.af_inet.id++; ++ setup_pre_routing(skb); ++ store_orig_dstaddr(skb); + -+ do { -+ char *data; -+ struct sk_buff * skb; ++ NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, ++ br_nf_pre_routing_finish); + -+ /* -+ * Get the memory we require with some space left for alignment. -+ */ -+ if (!(flags & MSG_DONTWAIT) || nfrags == 0) { -+ skb = sock_alloc_send_skb(sk, fraglen + hh_len + 15, -+ (flags & MSG_DONTWAIT), &err); -+ } else { -+ /* On a non-blocking write, we check for send buffer -+ * usage on the first fragment only. -+ */ -+ skb = sock_wmalloc(sk, fraglen + hh_len + 15, 1, -+ sk->allocation); -+ if (!skb) -+ err = -ENOBUFS; -+ } -+ if (skb == NULL) -+ goto error; ++ return NF_STOLEN; + -+ /* -+ * Fill in the control structures -+ */ ++inhdr_error: ++// IP_INC_STATS_BH(IpInHdrErrors); ++out: ++ return NF_DROP; ++} + -+ skb->priority = sk->priority; -+ skb->dst = dst_clone(&rt->u.dst); -+ skb_reserve(skb, hh_len); + -+ /* -+ * Find where to start putting bytes. -+ */ ++/* PF_BRIDGE/LOCAL_IN ************************************************/ ++/* The packet is locally destined, which requires a real ++ * dst_entry, so detach the fake one. On the way up, the ++ * packet would pass through PRE_ROUTING again (which already ++ * took place when the packet entered the bridge), but we ++ * register an IPv4 PRE_ROUTING 'sabotage' hook that will ++ * prevent this from happening. ++ */ ++static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) ++{ ++ struct sk_buff *skb = *pskb; ++ ++ if (skb->dst == (struct dst_entry *)&__fake_rtable) { ++ dst_release(skb->dst); ++ skb->dst = NULL; ++ } + -+ data = skb_put(skb, fraglen); -+ skb->nh.iph = (struct iphdr *)data; ++ return NF_ACCEPT; ++} + -+ /* -+ * Only write IP header onto non-raw packets -+ */ ++/* PF_BRIDGE/FORWARD *************************************************/ ++static int br_nf_forward_finish(struct sk_buff *skb) ++{ ++ struct nf_bridge_info *nf_bridge = skb->nf_bridge; ++ struct net_device *in; ++/* struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);*/ + -+ { -+ struct iphdr *iph = (struct iphdr *)data; -+ -+ iph->version = 4; -+ iph->ihl = 5; -+ if (opt) { -+ iph->ihl += opt->optlen>>2; -+ ip_options_build(skb, opt, -+ ipc->addr, rt, offset); -+ } -+ iph->tos = sk->protinfo.af_inet.tos; -+ iph->tot_len = htons(fraglen - fragheaderlen + iph->ihl*4); -+ iph->frag_off = htons(offset>>3)|mf|df; -+ iph->id = id; -+ if (!mf) { -+ if (offset || !df) { -+ /* Select an unpredictable ident only -+ * for packets without DF or having -+ * been fragmented. -+ */ -+ __ip_select_ident(iph, &rt->u.dst); -+ id = iph->id; -+ } ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug ^= (1 << NF_BR_FORWARD); ++#endif + -+ /* -+ * Any further fragments will have MF set. -+ */ -+ mf = htons(IP_MF); -+ } -+ if (rt->rt_type == RTN_MULTICAST) -+ iph->ttl = sk->protinfo.af_inet.mc_ttl; -+ else -+ iph->ttl = sk->protinfo.af_inet.ttl; -+ iph->protocol = sk->protocol; -+ iph->check = 0; -+ iph->saddr = rt->rt_src; -+ iph->daddr = rt->rt_dst; -+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); -+ data += iph->ihl*4; ++/* if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {*/ ++ in = nf_bridge->physindev; ++ if (nf_bridge->mask & BRNF_PKT_TYPE) { ++ skb->pkt_type = PACKET_OTHERHOST; ++ nf_bridge->mask ^= BRNF_PKT_TYPE; + } ++/* } else { ++ in = *((struct net_device **)(skb->cb)); ++ }*/ ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_push(skb, VLAN_HLEN); ++ skb->nh.raw -= VLAN_HLEN; ++ } ++ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, ++ skb->dev, br_forward_finish, 1); ++ return 0; ++} + -+ /* -+ * User data callback -+ */ ++/* This is the 'purely bridged' case. For IP, we pass the packet to ++ * netfilter with indev and outdev set to the bridge device, ++ * but we are still able to filter on the 'real' indev/outdev ++ * because of the ipt_physdev.c module. For ARP, indev and outdev are the ++ * bridge ports. ++ */ ++static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) ++{ ++ struct sk_buff *skb = *pskb; ++ struct nf_bridge_info *nf_bridge; ++ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); ++ int pf; + -+ if (getfrag(frag, data, offset, fraglen-fragheaderlen, skb)) { -+ err = -EFAULT; -+ kfree_skb(skb); -+ goto error; -+ } ++ if (!skb->nf_bridge) ++ return NF_ACCEPT; + -+ offset -= (maxfraglen-fragheaderlen); -+ fraglen = maxfraglen; ++ if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) ++ pf = PF_INET; ++ else ++ pf = PF_INET6; + -+ nfrags++; ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_pull(*pskb, VLAN_HLEN); ++ (*pskb)->nh.raw += VLAN_HLEN; ++ } + -+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, -+ skb->dst->dev, output_maybe_reroute); -+ if (err) { -+ if (err > 0) -+ err = sk->protinfo.af_inet.recverr ? net_xmit_errno(err) : 0; -+ if (err) -+ goto error; -+ } -+ } while (offset >= 0); ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug ^= (1 << NF_BR_FORWARD); ++#endif ++ nf_bridge = skb->nf_bridge; ++ if (skb->pkt_type == PACKET_OTHERHOST) { ++ skb->pkt_type = PACKET_HOST; ++ nf_bridge->mask |= BRNF_PKT_TYPE; ++ } + -+ if (nfrags>1) -+ ip_statistics[smp_processor_id()*2 + !in_softirq()].IpFragCreates += nfrags; -+out: -+ return 0; ++ /* The physdev module checks on this */ ++ nf_bridge->mask |= BRNF_BRIDGED; ++ nf_bridge->physoutdev = skb->dev; ++ ++ NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in), ++ bridge_parent(out), br_nf_forward_finish); + -+error: -+ IP_INC_STATS(IpOutDiscards); -+ if (nfrags>1) -+ ip_statistics[smp_processor_id()*2 + !in_softirq()].IpFragCreates += nfrags; -+ return err; ++ return NF_STOLEN; +} + +/* -+ * Fast path for unfragmented packets. -+ */ -+int ip_build_xmit(struct sock *sk, -+ int getfrag (const void *, -+ char *, -+ unsigned int, -+ unsigned int, -+ struct sk_buff *), -+ const void *frag, -+ unsigned length, -+ struct ipcm_cookie *ipc, -+ struct rtable *rt, -+ int flags) ++static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) +{ -+ int err; -+ struct sk_buff *skb; -+ int df; -+ struct iphdr *iph; ++ struct sk_buff *skb = *pskb; ++ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); ++ struct net_device **d = (struct net_device **)(skb->cb); + -+ /* -+ * Try the simple case first. This leaves fragmented frames, and by -+ * choice RAW frames within 20 bytes of maximum size(rare) to the long path -+ */ ++ if (!brnf_call_arptables) ++ return NF_ACCEPT; ++ ++ if (skb->protocol != __constant_htons(ETH_P_ARP)) { ++ if (!IS_VLAN_ARP) ++ return NF_ACCEPT; ++ skb_pull(*pskb, VLAN_HLEN); ++ (*pskb)->nh.raw += VLAN_HLEN; ++ } + -+ if (!sk->protinfo.af_inet.hdrincl) { -+ length += sizeof(struct iphdr); ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug ^= (1 << NF_BR_FORWARD); ++#endif + -+ /* -+ * Check for slow path. -+ */ -+ if (length > rt->u.dst.pmtu || ipc->opt != NULL) -+ return ip_build_xmit_slow(sk,getfrag,frag,length,ipc,rt,flags); -+ } else { -+ if (length > rt->u.dst.dev->mtu) { -+ ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, rt->u.dst.dev->mtu); -+ return -EMSGSIZE; ++ if (skb->nh.arph->ar_pln != 4) { ++ if (IS_VLAN_ARP) { ++ skb_push(*pskb, VLAN_HLEN); ++ (*pskb)->nh.raw -= VLAN_HLEN; + } ++ return NF_ACCEPT; + } -+ if (flags&MSG_PROBE) -+ goto out; ++ *d = (struct net_device *)in; ++ NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in, ++ (struct net_device *)out, br_nf_forward_finish); + -+ /* -+ * Do path mtu discovery if needed. -+ */ -+ df = 0; -+ if (ip_dont_fragment(sk, &rt->u.dst)) -+ df = htons(IP_DF); ++ return NF_STOLEN; ++} ++*/ + -+ /* -+ * Fast path for unfragmented frames without options. -+ */ -+ { -+ int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15; -+ -+ skb = sock_alloc_send_skb(sk, length+hh_len+15, -+ flags&MSG_DONTWAIT, &err); -+ if(skb==NULL) -+ goto error; -+ skb_reserve(skb, hh_len); -+ } -+ -+ skb->priority = sk->priority; -+ skb->dst = dst_clone(&rt->u.dst); -+ -+ skb->nh.iph = iph = (struct iphdr *)skb_put(skb, length); -+ -+ if(!sk->protinfo.af_inet.hdrincl) { -+ iph->version=4; -+ iph->ihl=5; -+ iph->tos=sk->protinfo.af_inet.tos; -+ iph->tot_len = htons(length); -+ iph->frag_off = df; -+ iph->ttl=sk->protinfo.af_inet.mc_ttl; -+ ip_select_ident(iph, &rt->u.dst, sk); -+ if (rt->rt_type != RTN_MULTICAST) -+ iph->ttl=sk->protinfo.af_inet.ttl; -+ iph->protocol=sk->protocol; -+ iph->saddr=rt->rt_src; -+ iph->daddr=rt->rt_dst; -+ iph->check=0; -+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); -+ err = getfrag(frag, ((char *)iph)+iph->ihl*4,0, length-iph->ihl*4, skb); ++/* PF_BRIDGE/LOCAL_OUT ***********************************************/ ++static int br_nf_local_out_finish(struct sk_buff *skb) ++{ ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug &= ~(1 << NF_BR_LOCAL_OUT); ++#endif ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_push(skb, VLAN_HLEN); ++ skb->nh.raw -= VLAN_HLEN; + } -+ else -+ err = getfrag(frag, (void *)iph, 0, length, skb); + -+ if (err) -+ goto error_fault; ++ NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, ++ br_forward_finish, NF_BR_PRI_FIRST + 1); + -+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, -+ output_maybe_reroute); -+ if (err > 0) -+ err = sk->protinfo.af_inet.recverr ? net_xmit_errno(err) : 0; -+ if (err) -+ goto error; -+out: + return 0; -+ -+error_fault: -+ err = -EFAULT; -+ kfree_skb(skb); -+error: -+ IP_INC_STATS(IpOutDiscards); -+ return err; +} + -+/* -+ * This IP datagram is too large to be sent in one piece. Break it up into -+ * smaller pieces (each of size equal to IP header plus -+ * a block of the data of the original IP data part) that will yet fit in a -+ * single device frame, and queue such a frame for sending. ++ ++/* This function sees both locally originated IP packets and forwarded ++ * IP packets (in both cases the destination device is a bridge ++ * device). It also sees bridged-and-DNAT'ed packets. ++ * To be able to filter on the physical bridge devices (with the ipt_physdev.c ++ * module), we steal packets destined to a bridge device away from the ++ * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later, ++ * when we have determined the real output device. This is done in here. + * -+ * Yes this is inefficient, feel free to submit a quicker one. ++ * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged ++ * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward() ++ * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority ++ * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor ++ * will be executed. ++ * Otherwise, if nf_bridge->physindev is NULL, the bridge-nf code never touched ++ * this packet before, and so the packet was locally originated. We fake ++ * the PF_INET/LOCAL_OUT hook. ++ * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed, ++ * so we fake the PF_INET/FORWARD hook. ipv4_sabotage_out() makes sure ++ * even routed packets that didn't arrive on a bridge interface have their ++ * nf_bridge->physindev set. + */ + -+int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ++static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) +{ -+ struct iphdr *iph; -+ int raw = 0; -+ int ptr; -+ struct net_device *dev; -+ struct sk_buff *skb2; -+ unsigned int mtu, hlen, left, len; -+ int offset; -+ int not_last_frag; -+ struct rtable *rt = (struct rtable*)skb->dst; -+ int err = 0; -+ -+ dev = rt->u.dst.dev; -+ -+ /* -+ * Point into the IP datagram header. -+ */ -+ -+ iph = skb->nh.iph; -+ -+ /* -+ * Setup starting values. -+ */ ++ struct net_device *realindev, *realoutdev; ++ struct sk_buff *skb = *pskb; ++ struct nf_bridge_info *nf_bridge; ++ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); ++ int pf; + -+ hlen = iph->ihl * 4; -+ left = skb->len - hlen; /* Space per frame */ -+ mtu = rt->u.dst.pmtu - hlen; /* Size of data space */ -+ ptr = raw + hlen; /* Where to start from */ ++ if (!skb->nf_bridge) ++ return NF_ACCEPT; + -+ /* -+ * Fragment the datagram. -+ */ ++ if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) ++ pf = PF_INET; ++ else ++ pf = PF_INET6; ++ ++#ifdef CONFIG_NETFILTER_DEBUG ++ /* Sometimes we get packets with NULL ->dst here (for example, ++ * running a dhcp client daemon triggers this). This should now ++ * be fixed, but let's keep the check around. */ ++ if (skb->dst == NULL) { ++ printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); ++ return NF_ACCEPT; ++ } ++#endif + -+ offset = (ntohs(iph->frag_off) & IP_OFFSET) << 3; -+ not_last_frag = iph->frag_off & htons(IP_MF); ++ nf_bridge = skb->nf_bridge; ++ nf_bridge->physoutdev = skb->dev; ++ realindev = nf_bridge->physindev; + -+ /* -+ * Keep copying data until we run out. ++ /* Bridged, take PF_BRIDGE/FORWARD. ++ * (see big note in front of br_nf_pre_routing_finish) + */ -+ -+ while(left > 0) { -+ len = left; -+ /* IF: it doesn't fit, use 'mtu' - the data space left */ -+ if (len > mtu) -+ len = mtu; -+ /* IF: we are not sending upto and including the packet end -+ then align the next start on an eight byte boundary */ -+ if (len < left) { -+ len &= ~7; ++ if (nf_bridge->mask & BRNF_BRIDGED_DNAT) { ++ if (nf_bridge->mask & BRNF_PKT_TYPE) { ++ skb->pkt_type = PACKET_OTHERHOST; ++ nf_bridge->mask ^= BRNF_PKT_TYPE; + } -+ /* -+ * Allocate buffer. -+ */ -+ -+ if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15,GFP_ATOMIC)) == NULL) { -+ NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n")); -+ err = -ENOMEM; -+ goto fail; ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_push(skb, VLAN_HLEN); ++ skb->nh.raw -= VLAN_HLEN; + } + -+ /* -+ * Set up data on packet -+ */ -+ -+ skb2->pkt_type = skb->pkt_type; -+ skb2->priority = skb->priority; -+ skb_reserve(skb2, (dev->hard_header_len+15)&~15); -+ skb_put(skb2, len + hlen); -+ skb2->nh.raw = skb2->data; -+ skb2->h.raw = skb2->data + hlen; -+ skb2->protocol = skb->protocol; -+ skb2->security = skb->security; -+ -+ /* -+ * Charge the memory for the fragment to any owner -+ * it might possess -+ */ -+ -+ if (skb->sk) -+ skb_set_owner_w(skb2, skb->sk); -+ skb2->dst = dst_clone(skb->dst); -+ skb2->dev = skb->dev; -+ -+ /* -+ * Copy the packet header into the new buffer. -+ */ -+ -+ memcpy(skb2->nh.raw, skb->data, hlen); -+ -+ /* -+ * Copy a block of the IP datagram. -+ */ -+ if (skb_copy_bits(skb, ptr, skb2->h.raw, len)) -+ BUG(); -+ left -= len; -+ -+ /* -+ * Fill in the new header fields. -+ */ -+ iph = skb2->nh.iph; -+ iph->frag_off = htons((offset >> 3)); -+ -+ /* ANK: dirty, but effective trick. Upgrade options only if -+ * the segment to be fragmented was THE FIRST (otherwise, -+ * options are already fixed) and make it ONCE -+ * on the initial skb, so that all the following fragments -+ * will inherit fixed options. -+ */ -+ if (offset == 0) -+ ip_options_fragment(skb); -+ -+ /* Copy the flags to each fragment. */ -+ IPCB(skb2)->flags = IPCB(skb)->flags; -+ -+ /* -+ * Added AC : If we are fragmenting a fragment that's not the -+ * last fragment then keep MF on each bit -+ */ -+ if (left > 0 || not_last_frag) -+ iph->frag_off |= htons(IP_MF); -+ ptr += len; -+ offset += len; ++ NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, ++ skb->dev, br_forward_finish); ++ goto out; ++ } ++ realoutdev = bridge_parent(skb->dev); + -+#ifdef CONFIG_NET_SCHED -+ skb2->tc_index = skb->tc_index; ++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) ++ /* iptables should match -o br0.x */ ++ if (nf_bridge->netoutdev) ++ realoutdev = nf_bridge->netoutdev; +#endif -+#ifdef CONFIG_NETFILTER -+ skb2->nfmark = skb->nfmark; -+ skb2->nfcache = skb->nfcache; -+ /* Connection association is same as pre-frag packet */ -+ skb2->nfct = skb->nfct; -+ nf_conntrack_get(skb2->nfct); ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_pull(skb, VLAN_HLEN); ++ (*pskb)->nh.raw += VLAN_HLEN; ++ } ++ /* IP forwarded traffic has a physindev, locally ++ * generated traffic hasn't. ++ */ ++ if (realindev != NULL) { ++ if (((nf_bridge->mask & BRNF_DONT_TAKE_PARENT) == 0) && ++ has_bridge_parent(realindev)) ++ realindev = bridge_parent(realindev); ++ NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev, ++ realoutdev, okfn, ++ NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1); ++ } else { +#ifdef CONFIG_NETFILTER_DEBUG -+ skb2->nf_debug = skb->nf_debug; -+#endif ++ skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT); +#endif + -+ /* -+ * Put this fragment into the sending queue. -+ */ -+ -+ IP_INC_STATS(IpFragCreates); -+ -+ iph->tot_len = htons(len + hlen); -+ -+ ip_send_check(iph); -+ -+ err = output(skb2); -+ if (err) -+ goto fail; ++ NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev, ++ realoutdev, okfn, ++ NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1); + } -+ kfree_skb(skb); -+ IP_INC_STATS(IpFragOKs); -+ return err; + -+fail: -+ kfree_skb(skb); -+ IP_INC_STATS(IpFragFails); -+ return err; ++out: ++ return NF_STOLEN; +} + -+/* -+ * Fetch data from kernel space and fill in checksum if needed. -+ */ -+static int ip_reply_glue_bits(const void *dptr, char *to, unsigned int offset, -+ unsigned int fraglen, struct sk_buff *skb) -+{ -+ struct ip_reply_arg *dp = (struct ip_reply_arg*)dptr; -+ u16 *pktp = (u16 *)to; -+ struct iovec *iov; -+ int len; -+ int hdrflag = 1; -+ -+ iov = &dp->iov[0]; -+ if (offset >= iov->iov_len) { -+ offset -= iov->iov_len; -+ iov++; -+ hdrflag = 0; -+ } -+ len = iov->iov_len - offset; -+ if (fraglen > len) { /* overlapping. */ -+ dp->csum = csum_partial_copy_nocheck(iov->iov_base+offset, to, len, -+ dp->csum); -+ offset = 0; -+ fraglen -= len; -+ to += len; -+ iov++; -+ } -+ -+ dp->csum = csum_partial_copy_nocheck(iov->iov_base+offset, to, fraglen, -+ dp->csum); -+ -+ if (hdrflag && dp->csumoffset) -+ *(pktp + dp->csumoffset) = csum_fold(dp->csum); /* fill in checksum */ -+ return 0; -+} -+ -+/* -+ * Generic function to send a packet as reply to another packet. -+ * Used to send TCP resets so far. ICMP should use this function too. -+ * -+ * Should run single threaded per socket because it uses the sock -+ * structure to pass arguments. -+ */ -+void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, -+ unsigned int len) -+{ -+ struct { -+ struct ip_options opt; -+ char data[40]; -+ } replyopts; -+ struct ipcm_cookie ipc; -+ u32 daddr; -+ struct rtable *rt = (struct rtable*)skb->dst; -+ -+ if (ip_options_echo(&replyopts.opt, skb)) -+ return; + -+ daddr = ipc.addr = rt->rt_src; -+ ipc.opt = NULL; -+ -+ if (replyopts.opt.optlen) { -+ ipc.opt = &replyopts.opt; ++/* PF_BRIDGE/POST_ROUTING ********************************************/ ++static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) ++{ ++ struct sk_buff *skb = *pskb; ++ struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; ++ struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet); ++ struct net_device *realoutdev = bridge_parent(skb->dev); ++ int pf; + -+ if (ipc.opt->srr) -+ daddr = replyopts.opt.faddr; ++#ifdef CONFIG_NETFILTER_DEBUG ++ /* Be very paranoid. This probably won't happen anymore, but let's ++ * keep the check just to be sure... */ ++ if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { ++ printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " ++ "bad mac.raw pointer."); ++ goto print_error; + } ++#endif + -+ if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0)) -+ return; ++ if (!nf_bridge) ++ return NF_ACCEPT; + -+ /* And let IP do all the hard work. ++ if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) ++ pf = PF_INET; ++ else ++ pf = PF_INET6; + -+ This chunk is not reenterable, hence spinlock. -+ Note that it uses the fact, that this function is called -+ with locally disabled BH and that sk cannot be already spinlocked. ++ /* Sometimes we get packets with NULL ->dst here (for example, ++ * running a dhcp client daemon triggers this). + */ -+ bh_lock_sock(sk); -+ sk->protinfo.af_inet.tos = skb->nh.iph->tos; -+ sk->priority = skb->priority; -+ sk->protocol = skb->nh.iph->protocol; -+ ip_build_xmit(sk, ip_reply_glue_bits, arg, len, &ipc, rt, MSG_DONTWAIT); -+ bh_unlock_sock(sk); -+ -+ ip_rt_put(rt); -+} -+ -+/* -+ * IP protocol layer initialiser -+ */ -+ -+static struct packet_type ip_packet_type = -+{ -+ __constant_htons(ETH_P_IP), -+ NULL, /* All devices */ -+ ip_rcv, -+ (void*)1, -+ NULL, -+}; -+ -+/* -+ * IP registers the packet type and then calls the subprotocol initialisers -+ */ -+ -+void __init ip_init(void) -+{ -+ dev_add_pack(&ip_packet_type); ++ if (skb->dst == NULL) ++ return NF_ACCEPT; + -+ ip_rt_init(); -+ inet_initpeers(); ++#ifdef CONFIG_NETFILTER_DEBUG ++ /* Sometimes we get packets with NULL ->dst here (for example, ++ * running a dhcp client daemon triggers this). This should now ++ * be fixed, but let's keep the check around. ++ */ ++ if (skb->dst == NULL) { ++ printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); ++ goto print_error; ++ } + -+#ifdef CONFIG_IP_MULTICAST -+ proc_net_create("igmp", 0, ip_mc_procinfo); ++ skb->nf_debug ^= (1 << NF_IP_POST_ROUTING); +#endif -+ proc_net_create("mcfilter", 0, ip_mcf_procinfo); -+} -diff -Nur linux-mips-cvs/net/ipv4/netfilter/Config.in linux-ebtables/net/ipv4/netfilter/Config.in ---- linux-mips-cvs/net/ipv4/netfilter/Config.in 2005-01-20 03:19:25.000000000 +0100 -+++ linux-ebtables/net/ipv4/netfilter/Config.in 2005-02-07 05:52:50.000000000 +0100 -@@ -44,6 +44,9 @@ - dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES - dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES - fi -+ if [ "$CONFIG_BRIDGE" != "n" ]; then -+ dep_tristate ' Physdev match support' CONFIG_IP_NF_MATCH_PHYSDEV $CONFIG_IP_NF_IPTABLES -+ fi - # The targets - dep_tristate ' Packet filtering' CONFIG_IP_NF_FILTER $CONFIG_IP_NF_IPTABLES - if [ "$CONFIG_IP_NF_FILTER" != "n" ]; then -diff -Nur linux-mips-cvs/net/ipv4/netfilter/Makefile linux-ebtables/net/ipv4/netfilter/Makefile ---- linux-mips-cvs/net/ipv4/netfilter/Makefile 2003-08-13 19:19:30.000000000 +0200 -+++ linux-ebtables/net/ipv4/netfilter/Makefile 2005-02-07 05:52:50.000000000 +0100 -@@ -87,6 +87,8 @@ - obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o - obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o - -+obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o + - # targets - obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o - obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o -diff -Nur linux-mips-cvs/net/ipv4/netfilter/ip_tables.c linux-ebtables/net/ipv4/netfilter/ip_tables.c ---- linux-mips-cvs/net/ipv4/netfilter/ip_tables.c 2005-01-20 03:19:25.000000000 +0100 -+++ linux-ebtables/net/ipv4/netfilter/ip_tables.c 2005-02-07 05:52:50.000000000 +0100 -@@ -118,12 +118,19 @@ - static inline int - ip_packet_match(const struct iphdr *ip, - const char *indev, -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ const char *physindev, -+#endif - const char *outdev, -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ const char *physoutdev, -+#endif - const struct ipt_ip *ipinfo, - int isfrag) - { - size_t i; - unsigned long ret; -+ unsigned long ret2 = 1; - - #define FWINV(bool,invflg) ((bool) ^ !!(ipinfo->invflags & invflg)) - -@@ -153,7 +160,15 @@ - & ((const unsigned long *)ipinfo->iniface_mask)[i]; - } - -- if (FWINV(ret != 0, IPT_INV_VIA_IN)) { -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ for (i = 0, ret2 = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { -+ ret2 |= (((const unsigned long *)physindev)[i] -+ ^ ((const unsigned long *)ipinfo->iniface)[i]) -+ & ((const unsigned long *)ipinfo->iniface_mask)[i]; ++ /* We assume any code from br_dev_queue_push_xmit onwards doesn't care ++ * about the value of skb->pkt_type. ++ */ ++ if (skb->pkt_type == PACKET_OTHERHOST) { ++ skb->pkt_type = PACKET_HOST; ++ nf_bridge->mask |= BRNF_PKT_TYPE; + } -+#endif + -+ if (FWINV(ret != 0 && ret2 != 0, IPT_INV_VIA_IN)) { - dprintf("VIA in mismatch (%s vs %s).%s\n", - indev, ipinfo->iniface, - ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":""); -@@ -166,7 +181,15 @@ - & ((const unsigned long *)ipinfo->outiface_mask)[i]; - } - -- if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ for (i = 0, ret2 = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { -+ ret2 |= (((const unsigned long *)physoutdev)[i] -+ ^ ((const unsigned long *)ipinfo->outiface)[i]) -+ & ((const unsigned long *)ipinfo->outiface_mask)[i]; ++ if (skb->protocol == __constant_htons(ETH_P_8021Q)) { ++ skb_pull(skb, VLAN_HLEN); ++ skb->nh.raw += VLAN_HLEN; + } -+#endif + -+ if (FWINV(ret != 0 && ret2 != 0, IPT_INV_VIA_OUT)) { - dprintf("VIA out mismatch (%s vs %s).%s\n", - outdev, ipinfo->outiface, - ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":""); -@@ -265,6 +288,9 @@ - /* Initializing verdict to NF_DROP keeps gcc happy. */ - unsigned int verdict = NF_DROP; - const char *indev, *outdev; -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ const char *physindev, *physoutdev; -+#endif - void *table_base; - struct ipt_entry *e, *back; - -@@ -274,6 +300,13 @@ - datalen = (*pskb)->len - ip->ihl * 4; - indev = in ? in->name : nulldevname; - outdev = out ? out->name : nulldevname; -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ physindev = ((*pskb)->nf_bridge && (*pskb)->nf_bridge->physindev) ? -+ (*pskb)->nf_bridge->physindev->name : nulldevname; -+ physoutdev = ((*pskb)->nf_bridge && (*pskb)->nf_bridge->physoutdev) ? -+ (*pskb)->nf_bridge->physoutdev->name : nulldevname; -+#endif ++ nf_bridge_save_header(skb); + - /* We handle fragments by dealing with the first fragment as - * if it was a normal packet. All other fragments are treated - * normally, except that they will NEVER match rules that ask -@@ -309,7 +342,15 @@ - IP_NF_ASSERT(e); - IP_NF_ASSERT(back); - (*pskb)->nfcache |= e->nfcache; -- if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) { -+ if (ip_packet_match(ip, indev, -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ physindev, -+#endif -+ outdev, -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ physoutdev, ++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) ++ if (nf_bridge->netoutdev) ++ realoutdev = nf_bridge->netoutdev; +#endif -+ &e->ip, offset)) { - struct ipt_entry_target *t; - - if (IPT_MATCH_ITERATE(e, do_match, -diff -Nur linux-mips-cvs/net/ipv4/netfilter/ipt_LOG.c linux-ebtables/net/ipv4/netfilter/ipt_LOG.c ---- linux-mips-cvs/net/ipv4/netfilter/ipt_LOG.c 2003-11-17 02:07:48.000000000 +0100 -+++ linux-ebtables/net/ipv4/netfilter/ipt_LOG.c 2005-02-07 05:52:50.000000000 +0100 -@@ -316,6 +316,18 @@ - loginfo->prefix, - in ? in->name : "", - out ? out->name : ""); -+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -+ if ((*pskb)->nf_bridge) { -+ struct net_device *physindev = (*pskb)->nf_bridge->physindev; -+ struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev; ++ NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, ++ realoutdev, br_dev_queue_push_xmit); + -+ if (physindev && in != physindev) -+ printk("PHYSIN=%s ", physindev->name); -+ if (physoutdev && out != physoutdev) -+ printk("PHYSOUT=%s ", physoutdev->name); ++ return NF_STOLEN; ++ ++#ifdef CONFIG_NETFILTER_DEBUG ++print_error: ++ if (skb->dev != NULL) { ++ printk("[%s]", skb->dev->name); ++ if (has_bridge_parent(skb->dev)) ++ printk("[%s]", bridge_parent(skb->dev)->name); + } ++ printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, ++ skb->data); ++ return NF_ACCEPT; +#endif ++} + - if (in && !out) { - /* MAC logging for input chain only. */ - printk("MAC="); -diff -Nur linux-mips-cvs/net/ipv4/netfilter/ipt_REJECT.c linux-ebtables/net/ipv4/netfilter/ipt_REJECT.c ---- linux-mips-cvs/net/ipv4/netfilter/ipt_REJECT.c 2005-01-20 03:19:25.000000000 +0100 -+++ linux-ebtables/net/ipv4/netfilter/ipt_REJECT.c 2005-02-07 05:52:50.000000000 +0100 -@@ -15,6 +15,9 @@ - #include <net/route.h> - #include <linux/netfilter_ipv4/ip_tables.h> - #include <linux/netfilter_ipv4/ipt_REJECT.h> -+#ifdef CONFIG_BRIDGE_NETFILTER -+#include <linux/netfilter_bridge.h> -+#endif - - #if 0 - #define DEBUGP printk -@@ -29,7 +32,13 @@ - struct rt_key key = {}; - struct rtable *rt; - -- if (hook != NF_IP_FORWARD) { -+ /* We don't require ip forwarding to be enabled to be able to -+ * send a RST reply for bridged traffic. */ -+ if (hook != NF_IP_FORWARD -+#ifdef CONFIG_BRIDGE_NETFILTER -+ || (skb->nf_bridge && skb->nf_bridge->mask & BRNF_BRIDGED) -+#endif -+ ) { - key.dst = iph->saddr; - if (hook == NF_IP_LOCAL_IN) - key.src = iph->daddr; -diff -Nur linux-mips-cvs/net/ipv4/netfilter/ipt_REJECT.c.orig linux-ebtables/net/ipv4/netfilter/ipt_REJECT.c.orig ---- linux-mips-cvs/net/ipv4/netfilter/ipt_REJECT.c.orig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/ipv4/netfilter/ipt_REJECT.c.orig 2005-01-20 03:19:25.000000000 +0100 -@@ -0,0 +1,426 @@ -+/* -+ * This is a module which is used for rejecting packets. -+ * Added support for customized reject packets (Jozsef Kadlecsik). -+ * Added support for ICMP type-3-code-13 (Maciej Soltysiak). [RFC 1812] -+ */ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/skbuff.h> -+#include <linux/ip.h> -+#include <linux/udp.h> -+#include <linux/icmp.h> -+#include <net/icmp.h> -+#include <net/ip.h> -+#include <net/tcp.h> -+#include <net/route.h> -+#include <linux/netfilter_ipv4/ip_tables.h> -+#include <linux/netfilter_ipv4/ipt_REJECT.h> + -+#if 0 -+#define DEBUGP printk -+#else -+#define DEBUGP(format, args...) -+#endif ++/* IPv4/SABOTAGE *****************************************************/ + -+static inline struct rtable *route_reverse(struct sk_buff *skb, int hook) ++/* Don't hand locally destined packets to PF_INET/PRE_ROUTING ++ * for the second time. ++ */ ++static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) +{ -+ struct iphdr *iph = skb->nh.iph; -+ struct dst_entry *odst; -+ struct rt_key key = {}; -+ struct rtable *rt; -+ -+ if (hook != NF_IP_FORWARD) { -+ key.dst = iph->saddr; -+ if (hook == NF_IP_LOCAL_IN) -+ key.src = iph->daddr; -+ key.tos = RT_TOS(iph->tos); -+ -+ if (ip_route_output_key(&rt, &key) != 0) -+ return NULL; -+ } else { -+ /* non-local src, find valid iif to satisfy -+ * rp-filter when calling ip_route_input. */ -+ key.dst = iph->daddr; -+ if (ip_route_output_key(&rt, &key) != 0) -+ return NULL; -+ -+ odst = skb->dst; -+ if (ip_route_input(skb, iph->saddr, iph->daddr, -+ RT_TOS(iph->tos), rt->u.dst.dev) != 0) { -+ dst_release(&rt->u.dst); -+ return NULL; -+ } -+ dst_release(&rt->u.dst); -+ rt = (struct rtable *)skb->dst; -+ skb->dst = odst; -+ } -+ -+ if (rt->u.dst.error) { -+ dst_release(&rt->u.dst); -+ rt = NULL; ++ if ((*pskb)->nf_bridge && ++ !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { ++ return NF_STOP; + } + -+ return rt; ++ return NF_ACCEPT; +} + -+/* Send RST reply */ -+static void send_reset(struct sk_buff *oldskb, int hook) ++/* Postpone execution of PF_INET/FORWARD, PF_INET/LOCAL_OUT ++ * and PF_INET/POST_ROUTING until we have done the forwarding ++ * decision in the bridge code and have determined skb->physoutdev. ++ */ ++static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, ++ const struct net_device *in, const struct net_device *out, ++ int (*okfn)(struct sk_buff *)) +{ -+ struct sk_buff *nskb; -+ struct tcphdr *otcph, *tcph; -+ struct rtable *rt; -+ unsigned int otcplen; -+ u_int16_t tmp_port; -+ u_int32_t tmp_addr; -+ int needs_ack; -+ int hh_len; -+ -+ /* IP header checks: fragment, too short. */ -+ if (oldskb->nh.iph->frag_off & htons(IP_OFFSET) -+ || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr)) -+ return; -+ -+ otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl); -+ otcplen = oldskb->len - oldskb->nh.iph->ihl*4; -+ -+ /* No RST for RST. */ -+ if (otcph->rst) -+ return; ++ struct sk_buff *skb = *pskb; + -+ /* Check checksum. */ -+ if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr, -+ oldskb->nh.iph->daddr, -+ csum_partial((char *)otcph, otcplen, 0)) != 0) -+ return; ++ if ((out->hard_start_xmit == br_dev_xmit && ++ okfn != br_nf_forward_finish && ++ okfn != br_nf_local_out_finish && ++ okfn != br_dev_queue_push_xmit) ++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) ++ || ((out->priv_flags & IFF_802_1Q_VLAN) && ++ VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) ++#endif ++ ) { ++ struct nf_bridge_info *nf_bridge; + -+ if ((rt = route_reverse(oldskb, hook)) == NULL) -+ return; ++ if (!skb->nf_bridge) { ++#ifdef CONFIG_SYSCTL ++ /* This code is executed while in the IP(v6) stack, ++ the version should be 4 or 6. We can't use ++ skb->protocol because that isn't set on ++ PF_INET(6)/LOCAL_OUT. */ ++ struct iphdr *ip = skb->nh.iph; + -+ hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15; ++ if (ip->version == 4 && !brnf_call_iptables) ++ return NF_ACCEPT; ++ else if (ip->version == 6 && !brnf_call_ip6tables) ++ return NF_ACCEPT; ++#endif ++ if (hook == NF_IP_POST_ROUTING) ++ return NF_ACCEPT; ++ if (!nf_bridge_alloc(skb)) ++ return NF_DROP; ++ } + ++ nf_bridge = skb->nf_bridge; + -+ /* Copy skb (even if skb is about to be dropped, we can't just -+ clone it because there may be other things, such as tcpdump, -+ interested in it). We also need to expand headroom in case -+ hh_len of incoming interface < hh_len of outgoing interface */ -+ nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb), -+ GFP_ATOMIC); -+ if (!nskb) { -+ dst_release(&rt->u.dst); -+ return; ++ /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we ++ * will need the indev then. For a brouter, the real indev ++ * can be a bridge port, so we make sure br_nf_local_out() ++ * doesn't use the bridge parent of the indev by using ++ * the BRNF_DONT_TAKE_PARENT mask. ++ */ ++ if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) { ++ nf_bridge->mask &= BRNF_DONT_TAKE_PARENT; ++ nf_bridge->physindev = (struct net_device *)in; ++ } ++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) ++ /* the iptables outdev is br0.x, not br0 */ ++ if (out->priv_flags & IFF_802_1Q_VLAN) ++ nf_bridge->netoutdev = (struct net_device *)out; ++#endif ++ return NF_STOP; + } + -+ dst_release(nskb->dst); -+ nskb->dst = &rt->u.dst; -+ -+ /* This packet will not be the same as the other: clear nf fields */ -+ nf_reset(nskb); -+ nskb->nfcache = 0; -+ nskb->nfmark = 0; -+ -+ tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); -+ -+ /* Swap source and dest */ -+ tmp_addr = nskb->nh.iph->saddr; -+ nskb->nh.iph->saddr = nskb->nh.iph->daddr; -+ nskb->nh.iph->daddr = tmp_addr; -+ tmp_port = tcph->source; -+ tcph->source = tcph->dest; -+ tcph->dest = tmp_port; -+ -+ /* Truncate to length (no data) */ -+ tcph->doff = sizeof(struct tcphdr)/4; -+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr)); -+ nskb->nh.iph->tot_len = htons(nskb->len); -+ -+ if (tcph->ack) { -+ needs_ack = 0; -+ tcph->seq = otcph->ack_seq; -+ tcph->ack_seq = 0; -+ } else { -+ needs_ack = 1; -+ tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin -+ + otcplen - (otcph->doff<<2)); -+ tcph->seq = 0; -+ } -+ -+ /* Reset flags */ -+ ((u_int8_t *)tcph)[13] = 0; -+ tcph->rst = 1; -+ tcph->ack = needs_ack; -+ -+ tcph->window = 0; -+ tcph->urg_ptr = 0; -+ -+ /* Adjust TCP checksum */ -+ tcph->check = 0; -+ tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), -+ nskb->nh.iph->saddr, -+ nskb->nh.iph->daddr, -+ csum_partial((char *)tcph, -+ sizeof(struct tcphdr), 0)); -+ -+ /* Adjust IP TTL, DF */ -+ nskb->nh.iph->ttl = MAXTTL; -+ /* Set DF, id = 0 */ -+ nskb->nh.iph->frag_off = htons(IP_DF); -+ nskb->nh.iph->id = 0; -+ -+ /* Adjust IP checksum */ -+ nskb->nh.iph->check = 0; -+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, -+ nskb->nh.iph->ihl); -+ -+ /* "Never happens" */ -+ if (nskb->len > nskb->dst->pmtu) -+ goto free_nskb; -+ -+ nf_ct_attach(nskb, oldskb); -+ -+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, -+ ip_finish_output); -+ return; -+ -+ free_nskb: -+ kfree_skb(nskb); ++ return NF_ACCEPT; +} + -+static void send_unreach(struct sk_buff *skb_in, int code) -+{ -+ struct iphdr *iph; -+ struct udphdr *udph; -+ struct icmphdr *icmph; -+ struct sk_buff *nskb; -+ u32 saddr; -+ u8 tos; -+ int hh_len, length; -+ struct rtable *rt = (struct rtable*)skb_in->dst; -+ unsigned char *data; -+ -+ if (!rt) -+ return; -+ -+ /* FIXME: Use sysctl number. --RR */ -+ if (!xrlim_allow(&rt->u.dst, 1*HZ)) -+ return; -+ -+ iph = skb_in->nh.iph; -+ -+ /* No replies to physical multicast/broadcast */ -+ if (skb_in->pkt_type!=PACKET_HOST) -+ return; -+ -+ /* Now check at the protocol level */ -+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST)) -+ return; -+ -+ /* Only reply to fragment 0. */ -+ if (iph->frag_off&htons(IP_OFFSET)) -+ return; ++/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent ++ * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input. ++ * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because ++ * ip_refrag() can return NF_STOLEN. ++ */ ++static struct nf_hook_ops br_nf_ops[] = { ++ { .hook = br_nf_pre_routing, ++ .pf = PF_BRIDGE, ++ .hooknum = NF_BR_PRE_ROUTING, ++ .priority = NF_BR_PRI_BRNF, }, ++ { .hook = br_nf_local_in, ++ .pf = PF_BRIDGE, ++ .hooknum = NF_BR_LOCAL_IN, ++ .priority = NF_BR_PRI_BRNF, }, ++ { .hook = br_nf_forward_ip, ++ .pf = PF_BRIDGE, ++ .hooknum = NF_BR_FORWARD, ++ .priority = NF_BR_PRI_BRNF /*- 1*/, }, ++/* { .hook = br_nf_forward_arp, ++ .pf = PF_BRIDGE, ++ .hooknum = NF_BR_FORWARD, ++ .priority = NF_BR_PRI_BRNF, },*/ ++ { .hook = br_nf_local_out, ++ .pf = PF_BRIDGE, ++ .hooknum = NF_BR_LOCAL_OUT, ++ .priority = NF_BR_PRI_FIRST, }, ++ { .hook = br_nf_post_routing, ++ .pf = PF_BRIDGE, ++ .hooknum = NF_BR_POST_ROUTING, ++ .priority = NF_BR_PRI_LAST, }, ++ { .hook = ip_sabotage_in, ++ .pf = PF_INET, ++ .hooknum = NF_IP_PRE_ROUTING, ++ .priority = NF_IP_PRI_FIRST, }, ++ { .hook = ip_sabotage_in, ++ .pf = PF_INET6, ++ .hooknum = NF_IP6_PRE_ROUTING, ++ .priority = NF_IP6_PRI_FIRST, }, ++ { .hook = ip_sabotage_out, ++ .pf = PF_INET, ++ .hooknum = NF_IP_FORWARD, ++ .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, }, ++ { .hook = ip_sabotage_out, ++ .pf = PF_INET6, ++ .hooknum = NF_IP6_FORWARD, ++ .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, }, ++ { .hook = ip_sabotage_out, ++ .pf = PF_INET, ++ .hooknum = NF_IP_LOCAL_OUT, ++ .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, }, ++ { .hook = ip_sabotage_out, ++ .pf = PF_INET6, ++ .hooknum = NF_IP6_LOCAL_OUT, ++ .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, }, ++ { .hook = ip_sabotage_out, ++ .pf = PF_INET, ++ .hooknum = NF_IP_POST_ROUTING, ++ .priority = NF_IP_PRI_FIRST, }, ++ { .hook = ip_sabotage_out, ++ .pf = PF_INET6, ++ .hooknum = NF_IP6_POST_ROUTING, ++ .priority = NF_IP6_PRI_FIRST, }, ++}; + -+ /* if UDP checksum is set, verify it's correct */ -+ if (iph->protocol == IPPROTO_UDP -+ && skb_in->tail-(u8*)iph >= sizeof(struct udphdr)) { -+ int datalen = skb_in->len - (iph->ihl<<2); -+ udph = (struct udphdr *)((char *)iph + (iph->ihl<<2)); -+ if (udph->check -+ && csum_tcpudp_magic(iph->saddr, iph->daddr, -+ datalen, IPPROTO_UDP, -+ csum_partial((char *)udph, datalen, -+ 0)) != 0) -+ return; -+ } -+ -+ /* If we send an ICMP error to an ICMP error a mess would result.. */ -+ if (iph->protocol == IPPROTO_ICMP -+ && skb_in->tail-(u8*)iph >= sizeof(struct icmphdr)) { -+ icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2)); -+ /* Between echo-reply (0) and timestamp (13), -+ everything except echo-request (8) is an error. -+ Also, anything greater than NR_ICMP_TYPES is -+ unknown, and hence should be treated as an error... */ -+ if ((icmph->type < ICMP_TIMESTAMP -+ && icmph->type != ICMP_ECHOREPLY -+ && icmph->type != ICMP_ECHO) -+ || icmph->type > NR_ICMP_TYPES) -+ return; -+ } -+ -+ saddr = iph->daddr; -+ if (!(rt->rt_flags & RTCF_LOCAL)) -+ saddr = 0; -+ -+ tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL; -+ -+ if (ip_route_output(&rt, iph->saddr, saddr, RT_TOS(tos), 0)) -+ return; ++#ifdef CONFIG_SYSCTL ++static ++int brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp, ++ void *buffer, size_t *lenp) ++{ ++ int ret; + -+ /* RFC says return as much as we can without exceeding 576 bytes. */ -+ length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr); ++ ret = proc_dointvec(ctl, write, filp, buffer, lenp); + -+ if (length > rt->u.dst.pmtu) -+ length = rt->u.dst.pmtu; -+ if (length > 576) -+ length = 576; ++ if (write && *(int *)(ctl->data)) ++ *(int *)(ctl->data) = 1; ++ return ret; ++} + -+ hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15; ++static ctl_table brnf_table[] = { ++ { ++ .ctl_name = NET_BRIDGE_NF_CALL_ARPTABLES, ++ .procname = "bridge-nf-call-arptables", ++ .data = &brnf_call_arptables, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = &brnf_sysctl_call_tables, ++ }, ++ { ++ .ctl_name = NET_BRIDGE_NF_CALL_IPTABLES, ++ .procname = "bridge-nf-call-iptables", ++ .data = &brnf_call_iptables, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = &brnf_sysctl_call_tables, ++ }, ++ { ++ .ctl_name = NET_BRIDGE_NF_CALL_IP6TABLES, ++ .procname = "bridge-nf-call-ip6tables", ++ .data = &brnf_call_ip6tables, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = &brnf_sysctl_call_tables, ++ }, ++ { ++ .ctl_name = NET_BRIDGE_NF_FILTER_VLAN_TAGGED, ++ .procname = "bridge-nf-filter-vlan-tagged", ++ .data = &brnf_filter_vlan_tagged, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = &brnf_sysctl_call_tables, ++ }, ++ { .ctl_name = 0 } ++}; + -+ nskb = alloc_skb(hh_len+15+length, GFP_ATOMIC); -+ if (!nskb) { -+ ip_rt_put(rt); -+ return; -+ } ++static ctl_table brnf_bridge_table[] = { ++ { ++ .ctl_name = NET_BRIDGE, ++ .procname = "bridge", ++ .mode = 0555, ++ .child = brnf_table, ++ }, ++ { .ctl_name = 0 } ++}; + -+ nskb->priority = 0; -+ nskb->dst = &rt->u.dst; -+ skb_reserve(nskb, hh_len); -+ -+ /* Set up IP header */ -+ iph = nskb->nh.iph -+ = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr)); -+ iph->version=4; -+ iph->ihl=5; -+ iph->tos=tos; -+ iph->tot_len = htons(length); -+ -+ /* PMTU discovery never applies to ICMP packets. */ -+ iph->frag_off = 0; -+ -+ iph->ttl = MAXTTL; -+ ip_select_ident(iph, &rt->u.dst, NULL); -+ iph->protocol=IPPROTO_ICMP; -+ iph->saddr=rt->rt_src; -+ iph->daddr=rt->rt_dst; -+ iph->check=0; -+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); -+ -+ /* Set up ICMP header. */ -+ icmph = nskb->h.icmph -+ = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr)); -+ icmph->type = ICMP_DEST_UNREACH; -+ icmph->code = code; -+ icmph->un.gateway = 0; -+ icmph->checksum = 0; -+ -+ /* Copy as much of original packet as will fit */ -+ data = skb_put(nskb, -+ length - sizeof(struct iphdr) - sizeof(struct icmphdr)); -+ /* FIXME: won't work with nonlinear skbs --RR */ -+ memcpy(data, skb_in->nh.iph, -+ length - sizeof(struct iphdr) - sizeof(struct icmphdr)); -+ icmph->checksum = ip_compute_csum((unsigned char *)icmph, -+ length - sizeof(struct iphdr)); -+ -+ nf_ct_attach(nskb, skb_in); -+ -+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, -+ ip_finish_output); -+} -+ -+static unsigned int reject(struct sk_buff **pskb, -+ unsigned int hooknum, -+ const struct net_device *in, -+ const struct net_device *out, -+ const void *targinfo, -+ void *userinfo) -+{ -+ const struct ipt_reject_info *reject = targinfo; -+ -+ /* Our naive response construction doesn't deal with IP -+ options, and probably shouldn't try. */ -+ if ((*pskb)->nh.iph->ihl<<2 != sizeof(struct iphdr)) -+ return NF_DROP; ++static ctl_table brnf_net_table[] = { ++ { ++ .ctl_name = CTL_NET, ++ .procname = "net", ++ .mode = 0555, ++ .child = brnf_bridge_table, ++ }, ++ { .ctl_name = 0 } ++}; ++#endif + -+ /* WARNING: This code causes reentry within iptables. -+ This means that the iptables jump stack is now crap. We -+ must return an absolute verdict. --RR */ -+ switch (reject->with) { -+ case IPT_ICMP_NET_UNREACHABLE: -+ send_unreach(*pskb, ICMP_NET_UNREACH); -+ break; -+ case IPT_ICMP_HOST_UNREACHABLE: -+ send_unreach(*pskb, ICMP_HOST_UNREACH); -+ break; -+ case IPT_ICMP_PROT_UNREACHABLE: -+ send_unreach(*pskb, ICMP_PROT_UNREACH); -+ break; -+ case IPT_ICMP_PORT_UNREACHABLE: -+ send_unreach(*pskb, ICMP_PORT_UNREACH); -+ break; -+ case IPT_ICMP_NET_PROHIBITED: -+ send_unreach(*pskb, ICMP_NET_ANO); -+ break; -+ case IPT_ICMP_HOST_PROHIBITED: -+ send_unreach(*pskb, ICMP_HOST_ANO); -+ break; -+ case IPT_ICMP_ADMIN_PROHIBITED: -+ send_unreach(*pskb, ICMP_PKT_FILTERED); -+ break; -+ case IPT_TCP_RESET: -+ send_reset(*pskb, hooknum); -+ case IPT_ICMP_ECHOREPLY: -+ /* Doesn't happen. */ -+ break; -+ } ++int br_netfilter_init(void) ++{ ++ int i; + -+ return NF_DROP; -+} ++ for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) { ++ int ret; + -+static int check(const char *tablename, -+ const struct ipt_entry *e, -+ void *targinfo, -+ unsigned int targinfosize, -+ unsigned int hook_mask) -+{ -+ const struct ipt_reject_info *rejinfo = targinfo; ++ if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0) ++ continue; + -+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { -+ DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); -+ return 0; -+ } ++ while (i--) ++ nf_unregister_hook(&br_nf_ops[i]); + -+ /* Only allow these for packet filtering. */ -+ if (strcmp(tablename, "filter") != 0) { -+ DEBUGP("REJECT: bad table `%s'.\n", tablename); -+ return 0; -+ } -+ if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) -+ | (1 << NF_IP_FORWARD) -+ | (1 << NF_IP_LOCAL_OUT))) != 0) { -+ DEBUGP("REJECT: bad hook mask %X\n", hook_mask); -+ return 0; ++ return ret; + } + -+ if (rejinfo->with == IPT_ICMP_ECHOREPLY) { -+ printk("REJECT: ECHOREPLY no longer supported.\n"); -+ return 0; -+ } else if (rejinfo->with == IPT_TCP_RESET) { -+ /* Must specify that it's a TCP packet */ -+ if (e->ip.proto != IPPROTO_TCP -+ || (e->ip.invflags & IPT_INV_PROTO)) { -+ DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n"); -+ return 0; -+ } ++#ifdef CONFIG_SYSCTL ++ brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0); ++ if (brnf_sysctl_header == NULL) { ++ printk(KERN_WARNING "br_netfilter: can't register to sysctl.\n"); ++ for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) ++ nf_unregister_hook(&br_nf_ops[i]); ++ return -EFAULT; + } ++#endif + -+ return 1; -+} -+ -+static struct ipt_target ipt_reject_reg -+= { { NULL, NULL }, "REJECT", reject, check, NULL, THIS_MODULE }; ++ printk(KERN_NOTICE "Bridge firewalling registered\n"); + -+static int __init init(void) -+{ -+ if (ipt_register_target(&ipt_reject_reg)) -+ return -EINVAL; + return 0; +} + -+static void __exit fini(void) ++void br_netfilter_fini(void) +{ -+ ipt_unregister_target(&ipt_reject_reg); -+} ++ int i; + -+module_init(init); -+module_exit(fini); -+MODULE_LICENSE("GPL"); -diff -Nur linux-mips-cvs/net/ipv4/netfilter/ipt_physdev.c linux-ebtables/net/ipv4/netfilter/ipt_physdev.c ---- linux-mips-cvs/net/ipv4/netfilter/ipt_physdev.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-ebtables/net/ipv4/netfilter/ipt_physdev.c 2005-02-07 05:52:50.000000000 +0100 ++ for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--) ++ nf_unregister_hook(&br_nf_ops[i]); ++#ifdef CONFIG_SYSCTL ++ unregister_sysctl_table(brnf_sysctl_header); ++#endif ++ ++} +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/net/ipv4/netfilter/ipt_physdev.c 2005-03-14 00:00:30.000000000 +0100 @@ -0,0 +1,127 @@ +/* Kernel module to match the bridge port in and + * out device for IP packets coming into contact with a bridge. */ @@ -9353,3 +6925,88 @@ diff -Nur linux-mips-cvs/net/ipv4/netfilter/ipt_physdev.c linux-ebtables/net/ipv +module_exit(fini); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; +--- /dev/null 2005-03-14 20:10:29.001600248 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/netfilter_ipv4/ipt_physdev.h 2005-03-14 21:24:30.000000000 +0100 +@@ -0,0 +1,24 @@ ++#ifndef _IPT_PHYSDEV_H ++#define _IPT_PHYSDEV_H ++ ++#ifdef __KERNEL__ ++#include <linux/if.h> ++#endif ++ ++#define IPT_PHYSDEV_OP_IN 0x01 ++#define IPT_PHYSDEV_OP_OUT 0x02 ++#define IPT_PHYSDEV_OP_BRIDGED 0x04 ++#define IPT_PHYSDEV_OP_ISIN 0x08 ++#define IPT_PHYSDEV_OP_ISOUT 0x10 ++#define IPT_PHYSDEV_OP_MASK (0x20 - 1) ++ ++struct ipt_physdev_info { ++ char physindev[IFNAMSIZ]; ++ char in_mask[IFNAMSIZ]; ++ char physoutdev[IFNAMSIZ]; ++ char out_mask[IFNAMSIZ]; ++ u_int8_t invert; ++ u_int8_t bitmask; ++}; ++ ++#endif /*_IPT_PHYSDEV_H*/ +--- linux-2.4.29/net/8021q/vlan_dev.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/8021q/vlan_dev.c 2005-03-14 00:00:30.000000000 +0100 +@@ -488,6 +488,10 @@ int vlan_dev_hard_start_xmit(struct sk_b + stats->tx_packets++; /* for statics only */ + stats->tx_bytes += skb->len; + ++ skb->protocol = __constant_htons(ETH_P_8021Q); ++ skb->mac.raw -= VLAN_HLEN; ++ skb->nh.raw -= VLAN_HLEN; ++ + skb->dev = VLAN_DEV_INFO(dev)->real_dev; + dev_queue_xmit(skb); + +--- linux-2.4.29/include/linux/sysctl.h 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/include/linux/sysctl.h 2005-03-14 21:07:18.000000000 +0100 +@@ -608,6 +608,15 @@ enum { + NET_DECNET_CONF_DEV_STATE = 7 + }; + ++/* /proc/sys/net/bridge */ ++enum { ++ NET_BRIDGE_NF_CALL_ARPTABLES = 1, ++ NET_BRIDGE_NF_CALL_IPTABLES = 2, ++ NET_BRIDGE_NF_CALL_IP6TABLES = 3, ++ NET_BRIDGE_NF_FILTER_VLAN_TAGGED = 4, ++}; ++ ++ + /* CTL_PROC names: */ + + /* CTL_FS names: */ +--- linux-2.4.29/net/ipv4/netfilter/ipt_REJECT.c 2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.29-ebt-brnf/net/ipv4/netfilter/ipt_REJECT.c 2005-03-14 00:00:30.000000000 +0100 +@@ -15,6 +15,9 @@ + #include <net/route.h> + #include <linux/netfilter_ipv4/ip_tables.h> + #include <linux/netfilter_ipv4/ipt_REJECT.h> ++#ifdef CONFIG_BRIDGE_NETFILTER ++#include <linux/netfilter_bridge.h> ++#endif + + #if 0 + #define DEBUGP printk +@@ -29,7 +32,13 @@ static inline struct rtable *route_rever + struct rt_key key = {}; + struct rtable *rt; + +- if (hook != NF_IP_FORWARD) { ++ /* We don't require ip forwarding to be enabled to be able to ++ * send a RST reply for bridged traffic. */ ++ if (hook != NF_IP_FORWARD ++#ifdef CONFIG_BRIDGE_NETFILTER ++ || (skb->nf_bridge && skb->nf_bridge->mask & BRNF_BRIDGED) ++#endif ++ ) { + key.dst = iph->saddr; + if (hook == NF_IP_LOCAL_IN) + key.src = iph->daddr; |