Merge branch 'release' of master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 13 Oct 2005 23:10:54 +0000 (16:10 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 13 Oct 2005 23:10:54 +0000 (16:10 -0700)
71 files changed:
Documentation/connector/connector.txt
arch/arm/Makefile
arch/arm/kernel/armksyms.c
arch/arm/kernel/entry-common.S
arch/arm/mach-s3c2410/mach-anubis.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2410/s3c2440.c
arch/arm/mach-s3c2410/time.c
arch/arm/mm/alignment.c
arch/arm/nwfpe/fpa11.c
arch/arm/nwfpe/fpa11.h
arch/arm/nwfpe/fpa11_cprt.c
arch/arm/nwfpe/fpopcode.h
arch/arm/nwfpe/softfloat.h
arch/cris/arch-v32/kernel/smp.c
arch/ppc/kernel/cputable.c
arch/sh/kernel/smp.c
arch/sparc/Kconfig
arch/sparc/defconfig
arch/sparc64/kernel/dtlb_base.S
arch/sparc64/kernel/dtlb_prot.S
arch/sparc64/kernel/head.S
arch/sparc64/kernel/itlb_base.S
arch/sparc64/kernel/ktlb.S
arch/sparc64/mm/init.c
arch/um/drivers/Makefile
arch/um/drivers/ubd_kern.c
arch/um/drivers/ubd_user.c [new file with mode: 0644]
arch/um/include/aio.h
arch/um/include/os.h
arch/um/os-Linux/aio.c
drivers/net/e100.c
drivers/scsi/sata_nv.c
drivers/serial/imx.c
drivers/serial/pxa.c
drivers/serial/s3c2410.c
drivers/serial/sunsab.c
drivers/serial/sunzilog.c
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-s3c2410/hardware.h
include/asm-powerpc/timex.h
include/asm-ppc/cputable.h
include/linux/cpumask.h
include/linux/netfilter/nfnetlink.h
include/linux/netfilter/nfnetlink_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack_protocol.h
include/linux/netfilter_ipv4/ip_conntrack_tuple.h
include/linux/netfilter_ipv4/ip_nat.h
include/linux/netpoll.h
include/net/inet_timewait_sock.h
net/bridge/br_if.c
net/bridge/netfilter/ebtables.c
net/dccp/ccid.h
net/dccp/input.c
net/ipv4/esp4.c
net/ipv4/inet_timewait_sock.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_conntrack_proto_icmp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/tcp_output.c
net/ipv6/esp6.c
net/ipv6/netfilter/ip6_tables.c
net/netfilter/nfnetlink.c
net/sched/Kconfig

index 54a0a14bfbe3dee409bda417cc738fc7557afa82..57a314b14cf8ef948f1529c96fbfd5d74223d137 100644 (file)
@@ -131,3 +131,47 @@ Netlink itself is not reliable protocol, that means that messages can
 be lost due to memory pressure or process' receiving queue overflowed,
 so caller is warned must be prepared. That is why struct cn_msg [main
 connector's message header] contains u32 seq and u32 ack fields.
+
+/*****************************************/
+Userspace usage.
+/*****************************************/
+2.6.14 has a new netlink socket implementation, which by default does not
+allow to send data to netlink groups other than 1.
+So, if to use netlink socket (for example using connector) 
+with different group number userspace application must subscribe to 
+that group. It can be achieved by following pseudocode:
+
+s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+
+l_local.nl_family = AF_NETLINK;
+l_local.nl_groups = 12345;
+l_local.nl_pid = 0;
+
+if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
+       perror("bind");
+       close(s);
+       return -1;
+}
+
+{
+       int on = l_local.nl_groups;
+       setsockopt(s, 270, 1, &on, sizeof(on));
+}
+
+Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket
+option. To drop multicast subscription one should call above socket option
+with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
+
+2.6.14 netlink code only allows to select a group which is less or equal to
+the maximum group number, which is used at netlink_kernel_create() time.
+In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use
+group number 12345, you must increment CN_NETLINK_USERS to that number.
+Additional 0xf numbers are allocated to be used by non-in-kernel users.
+
+Due to this limitation, group 0xffffffff does not work now, so one can
+not use add/remove connector's group notifications, but as far as I know, 
+only cn_test.c test module used it.
+
+Some work in netlink area is still being done, so things can be changed in
+2.6.15 timeframe, if it will happen, documentation will be updated for that
+kernel.
index 7779f2d1acad00845f99f6b5931650d3205ac085..299bc04687027aa5fd5254050ab3a62648ca12ca 100644 (file)
@@ -53,7 +53,7 @@ tune-$(CONFIG_CPU_ARM926T)    :=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)       :=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)      :=-mtune=strongarm1100
 tune-$(CONFIG_CPU_XSCALE)      :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
-tune-$(CONFIG_CPU_V6)          :=-mtune=strongarm
+tune-$(CONFIG_CPU_V6)          :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
 
 # Need -Uarm for gcc < 3.x
 CFLAGS_ABI     :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
index 835d450797a1e29378986f05b3e5ac852afd2a36..7b17a87a3311af3ece561f3cbc19debf459e4a8c 100644 (file)
@@ -45,8 +45,8 @@ extern void fp_enter(void);
 
 #define EXPORT_SYMBOL_ALIAS(sym,orig)          \
  EXPORT_CRC_ALIAS(sym)                         \
const struct kernel_symbol __ksymtab_##sym    \
-  __attribute__((section("__ksymtab"))) =      \
static const struct kernel_symbol __ksymtab_##sym     \
+  __attribute_used__ __attribute__((section("__ksymtab"))) =   \
     { (unsigned long)&orig, #sym };
 
 /*
index 81d450ac3fab2e1351b15860d9e6bda727261198..066597f4345a6716bf0284200076303f6a85602b 100644 (file)
@@ -106,15 +106,10 @@ ENTRY(ret_from_fork)
        .endm
 
 .Larm700bug:
-       ldr     r0, [sp, #S_PSR]                @ Get calling cpsr
-       sub     lr, lr, #4
-       str     lr, [r8]
-       msr     spsr_cxsf, r0
        ldmia   sp, {r0 - lr}^                  @ Get calling r0 - lr
        mov     r0, r0
-       ldr     lr, [sp, #S_PC]                 @ Get PC
        add     sp, sp, #S_FRAME_SIZE
-       movs    pc, lr
+       subs    pc, lr, #4
 #else
        .macro  arm710_bug_check, instr, temp
        .endm
index 7c05f27fe1d63c564c1277f34fd2f1519bb61db3..5ae80f4e3e672ca3dcf187aa4e96fdc1f27a1752 100644 (file)
@@ -125,7 +125,7 @@ static int external_map[]   = { 2 };
 static int chip0_map[]      = { 0 };
 static int chip1_map[]      = { 1 };
 
-struct mtd_partition anubis_default_nand_part[] = {
+static struct mtd_partition anubis_default_nand_part[] = {
        [0] = {
                .name   = "Boot Agent",
                .size   = SZ_16K,
index ed1f07d7252fe08e1ce6c57e66789a68a914c185..8ca955984645fec9745da911f7573cd68434ab3d 100644 (file)
@@ -230,7 +230,7 @@ static int chip0_map[] = { 1 };
 static int chip1_map[] = { 2 };
 static int chip2_map[] = { 3 };
 
-struct mtd_partition bast_default_nand_part[] = {
+static struct mtd_partition bast_default_nand_part[] = {
        [0] = {
                .name   = "Boot Agent",
                .size   = SZ_16K,
@@ -340,7 +340,7 @@ static struct resource bast_dm9k_resource[] = {
  * better IO routines can be written and tested
 */
 
-struct dm9000_plat_data bast_dm9k_platdata = {
+static struct dm9000_plat_data bast_dm9k_platdata = {
        .flags          = DM9000_PLATF_16BITONLY
 };
 
index 663a7f98fc0b94d9ec349266c8cbf0b04c6d61dc..46b259673c18156606f6ffb190ce69790d4b5274 100644 (file)
@@ -288,7 +288,7 @@ static struct resource vr1000_dm9k1_resource[] = {
  * better IO routines can be written and tested
 */
 
-struct dm9000_plat_data vr1000_dm9k_platdata = {
+static struct dm9000_plat_data vr1000_dm9k_platdata = {
        .flags          = DM9000_PLATF_16BITONLY,
 };
 
index 0b88993dfd27c514c181f6adc83aeb898aaf28d7..a8bf5ec826028c44db4b0ef22b81dc11421affdd 100644 (file)
@@ -125,9 +125,6 @@ static struct platform_device *uart_devices[] __initdata = {
        &s3c_uart2
 };
 
-/* store our uart devices for the serial driver console */
-struct platform_device *s3c2410_uart_devices[3];
-
 static int s3c2410_uart_count = 0;
 
 /* uart registration process */
index d4c8281b55f64a5c3a7a4f2d4fef2c6433215d25..833fa36bce057764843e3be433d406fd1ec2f3ed 100644 (file)
@@ -151,7 +151,7 @@ void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 #ifdef CONFIG_PM
 
-struct sleep_save s3c2440_sleep[] = {
+static struct sleep_save s3c2440_sleep[] = {
        SAVE_ITEM(S3C2440_DSC0),
        SAVE_ITEM(S3C2440_DSC1),
        SAVE_ITEM(S3C2440_GPJDAT),
@@ -260,7 +260,7 @@ void __init s3c2440_init_clocks(int xtal)
  * as a driver which may support both 2410 and 2440 may try and use it.
 */
 
-int __init s3c2440_core_init(void)
+static int __init s3c2440_core_init(void)
 {
        return sysdev_class_register(&s3c2440_sysclass);
 }
index c0acfb2ad790a711c877afda5195be642288f690..8a00e3c3cd089cf3bec4f192c72322cee95ebd93 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/hardware/clock.h>
 
 #include "clock.h"
+#include "cpu.h"
 
 static unsigned long timer_startval;
 static unsigned long timer_usec_ticks;
index f35e69e9c65c5da49deb71cb27fac2e4f143051d..705c98921c372e034af6b21ecf569872393cbe43 100644 (file)
@@ -111,7 +111,7 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
 }
 
 static int proc_alignment_write(struct file *file, const char __user *buffer,
-                              unsigned long count, void *data)
+                               unsigned long count, void *data)
 {
        char mode;
 
@@ -119,7 +119,7 @@ static int proc_alignment_write(struct file *file, const char __user *buffer,
                if (get_user(mode, buffer))
                        return -EFAULT;
                if (mode >= '0' && mode <= '5')
-                          ai_usermode = mode - '0';
+                       ai_usermode = mode - '0';
        }
        return count;
 }
@@ -262,7 +262,7 @@ union offset_union {
                        goto fault;                             \
        } while (0)
 
-#define put32_unaligned_check(val,addr)         \
+#define put32_unaligned_check(val,addr) \
        __put32_unaligned_check("strb", val, addr)
 
 #define put32t_unaligned_check(val,addr) \
@@ -306,19 +306,19 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
        return TYPE_LDST;
 
  user:
-       if (LDST_L_BIT(instr)) {
-               unsigned long val;
-               get16t_unaligned_check(val, addr);
+       if (LDST_L_BIT(instr)) {
+               unsigned long val;
+               get16t_unaligned_check(val, addr);
 
-               /* signed half-word? */
-               if (instr & 0x40)
-                       val = (signed long)((signed short) val);
+               /* signed half-word? */
+               if (instr & 0x40)
+                       val = (signed long)((signed short) val);
 
-               regs->uregs[rd] = val;
-       } else
-               put16t_unaligned_check(regs->uregs[rd], addr);
+               regs->uregs[rd] = val;
+       } else
+               put16t_unaligned_check(regs->uregs[rd], addr);
 
-       return TYPE_LDST;
+       return TYPE_LDST;
 
  fault:
        return TYPE_FAULT;
@@ -342,11 +342,11 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
                unsigned long val;
                get32_unaligned_check(val, addr);
                regs->uregs[rd] = val;
-               get32_unaligned_check(val, addr+4);
-               regs->uregs[rd+1] = val;
+               get32_unaligned_check(val, addr + 4);
+               regs->uregs[rd + 1] = val;
        } else {
                put32_unaligned_check(regs->uregs[rd], addr);
-               put32_unaligned_check(regs->uregs[rd+1], addr+4);
+               put32_unaligned_check(regs->uregs[rd + 1], addr + 4);
        }
 
        return TYPE_LDST;
@@ -356,11 +356,11 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
                unsigned long val;
                get32t_unaligned_check(val, addr);
                regs->uregs[rd] = val;
-               get32t_unaligned_check(val, addr+4);
-               regs->uregs[rd+1] = val;
+               get32t_unaligned_check(val, addr + 4);
+               regs->uregs[rd + 1] = val;
        } else {
                put32t_unaligned_check(regs->uregs[rd], addr);
-               put32t_unaligned_check(regs->uregs[rd+1], addr+4);
+               put32t_unaligned_check(regs->uregs[rd + 1], addr + 4);
        }
 
        return TYPE_LDST;
@@ -443,7 +443,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg
        if (LDST_P_EQ_U(instr)) /* U = P */
                eaddr += 4;
 
-       /* 
+       /*
         * For alignment faults on the ARM922T/ARM920T the MMU  makes
         * the FSR (and hence addr) equal to the updated base address
         * of the multiple access rather than the restored value.
@@ -570,7 +570,7 @@ thumb2arm(u16 tinstr)
        /* 6.5.1 Format 3: */
        case 0x4800 >> 11:                              /* 7.1.28 LDR(3) */
                /* NOTE: This case is not technically possible. We're
-                *       loading 32-bit memory data via PC relative
+                *       loading 32-bit memory data via PC relative
                 *       addressing mode. So we can and should eliminate
                 *       this case. But I'll leave it here for now.
                 */
@@ -642,7 +642,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
        if (fault) {
                type = TYPE_FAULT;
-               goto bad_or_fault;
+               goto bad_or_fault;
        }
 
        if (user_mode(regs))
index 7690f731ee8706227acdf3b1f56de14f2b906839..7b3d74d73c809c7c8d1855dcca4794ede2cc9316 100644 (file)
 #include <linux/string.h>
 #include <asm/system.h>
 
-/* forward declarations */
-unsigned int EmulateCPDO(const unsigned int);
-unsigned int EmulateCPDT(const unsigned int);
-unsigned int EmulateCPRT(const unsigned int);
-
 /* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
 static void resetFPA11(void)
 {
index 93523ae4b7a1f028b6772de5d8f7455b27400c57..9677ae8448e85f92ee742fe900faac31c70600a5 100644 (file)
@@ -95,4 +95,24 @@ extern int8 SetRoundingMode(const unsigned int);
 extern int8 SetRoundingPrecision(const unsigned int);
 extern void nwfpe_init_fpa(union fp_state *fp);
 
+extern unsigned int EmulateAll(unsigned int opcode);
+
+extern unsigned int EmulateCPDT(const unsigned int opcode);
+extern unsigned int EmulateCPDO(const unsigned int opcode);
+extern unsigned int EmulateCPRT(const unsigned int opcode);
+
+/* fpa11_cpdt.c */
+extern unsigned int PerformLDF(const unsigned int opcode);
+extern unsigned int PerformSTF(const unsigned int opcode);
+extern unsigned int PerformLFM(const unsigned int opcode);
+extern unsigned int PerformSFM(const unsigned int opcode);
+
+/* single_cpdo.c */
+
+extern unsigned int SingleCPDO(struct roundingData *roundData,
+                              const unsigned int opcode, FPREG * rFd);
+/* double_cpdo.c */
+extern unsigned int DoubleCPDO(struct roundingData *roundData,
+                              const unsigned int opcode, FPREG * rFd);
+
 #endif
index adf8d3000540f9c6f774024ff22d720507a2e24f..7c67023655e41c6543fb1b31a246f91fbd91499f 100644 (file)
 #include "fpa11.inl"
 #include "fpmodule.h"
 #include "fpmodule.inl"
+#include "softfloat.h"
 
 #ifdef CONFIG_FPE_NWFPE_XP
 extern flag floatx80_is_nan(floatx80);
 #endif
-extern flag float64_is_nan(float64);
-extern flag float32_is_nan(float32);
 
 unsigned int PerformFLT(const unsigned int opcode);
 unsigned int PerformFIX(const unsigned int opcode);
index 1777e92a88e69c73db5a0fa67438ff8520a9d56a..6528e081c83f59f527139d5c48d1a7556513fd30 100644 (file)
@@ -476,4 +476,10 @@ static inline unsigned int getDestinationSize(const unsigned int opcode)
        return (nRc);
 }
 
+extern unsigned int checkCondition(const unsigned int opcode,
+                                  const unsigned int ccodes);
+
+extern const float64 float64Constant[];
+extern const float32 float32Constant[];
+
 #endif
index 1c8799b9ee4d1399d209f5b4e0ed669b5ed0949d..14151700b6b2f00e3722bd7b852d7b7404f31606 100644 (file)
@@ -265,4 +265,7 @@ static inline flag float64_lt_nocheck(float64 a, float64 b)
        return (a != b) && (aSign ^ (a < b));
 }
 
+extern flag float32_is_nan( float32 a );
+extern flag float64_is_nan( float64 a );
+
 #endif
index 2c5cae04a95c8d794d3f2f2babf15aee80086939..957f551ba5ce21602467506a4c7f6f5276a1523e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/cpumask.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
 #define IPI_SCHEDULE 1
 #define IPI_CALL 2
@@ -28,6 +29,7 @@ spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED};
 /* CPU masks */
 cpumask_t cpu_online_map = CPU_MASK_NONE;
 cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
+EXPORT_SYMBOL(phys_cpu_present_map);
 
 /* Variables used during SMP boot */
 volatile int cpu_now_booting = 0;
index 546e1ea4cafa31a6bb126dfce2fdcbde2e3fe6d3..6b76cf58d9e068c3ac6687a7f20d1bf6c61bac9c 100644 (file)
@@ -91,7 +91,7 @@ struct cpu_spec       cpu_specs[] = {
                .cpu_features           = CPU_FTR_COMMON | CPU_FTR_601 |
                        CPU_FTR_HPTE_TABLE,
                .cpu_user_features      = COMMON_PPC | PPC_FEATURE_601_INSTR |
-                       PPC_FEATURE_UNIFIED_CACHE,
+                       PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .cpu_setup              = __setup_cpu_601
@@ -745,7 +745,8 @@ struct cpu_spec     cpu_specs[] = {
                .cpu_name               = "403GCX",
                .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
                        CPU_FTR_USE_TB,
-               .cpu_user_features      = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+               .cpu_user_features      = PPC_FEATURE_32 |
+                       PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
                .icache_bsize           = 16,
                .dcache_bsize           = 16,
        },
index 56a39d69e080dae1b12fade6656ea18c6d5479a2..5ecefc02896a3a07e030a3013b0023da96c15e9e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 
 #include <asm/atomic.h>
 #include <asm/processor.h>
@@ -39,6 +40,8 @@ struct sh_cpuinfo cpu_data[NR_CPUS];
 extern void per_cpu_trap_init(void);
 
 cpumask_t cpu_possible_map;
+EXPORT_SYMBOL(cpu_possible_map);
+
 cpumask_t cpu_online_map;
 static atomic_t cpus_booted = ATOMIC_INIT(0);
 
index f7c51b869049b1bcd4bf4d9c740fbcf3bd57d0ec..6537445dac0e8e30b519505d3639dfec42995e60 100644 (file)
@@ -21,10 +21,6 @@ config GENERIC_ISA_DMA
        bool
        default y
 
-config GENERIC_IOMAP
-       bool
-       default y
-
 source "init/Kconfig"
 
 menu "General machine setup"
index 8a3aef1e22f511cb5aba08294fba2665a54d80b5..a69856263009fc63efaa74cde0730994fe689ace 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_MMU=y
 CONFIG_UID16=y
 CONFIG_HIGHMEM=y
 CONFIG_GENERIC_ISA_DMA=y
-CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
index 702d349c1e88f7d22cf208f93150913600f78a26..6528786840c06bfb5c480abdfe706bcfa257eedc 100644 (file)
  * be guaranteed to be 0 ... mmu_context.h does guarantee this
  * by only using 10 bits in the hwcontext value.
  */
-#define CREATE_VPTE_OFFSET1(r1, r2)
+#define CREATE_VPTE_OFFSET1(r1, r2) nop
 #define CREATE_VPTE_OFFSET2(r1, r2) \
                                srax    r1, 10, r2
-#define CREATE_VPTE_NOP                nop
 #else
 #define CREATE_VPTE_OFFSET1(r1, r2) \
                                srax    r1, PAGE_SHIFT, r2
 #define CREATE_VPTE_OFFSET2(r1, r2) \
                                sllx    r2, 3, r2
-#define CREATE_VPTE_NOP
 #endif
 
 /* DTLB ** ICACHE line 1: Quick user TLB misses                */
+       mov             TLB_SFSR, %g1
        ldxa            [%g1 + %g1] ASI_DMMU, %g4       ! Get TAG_ACCESS
        andcc           %g4, TAG_CONTEXT_BITS, %g0      ! From Nucleus?
 from_tl1_trap:
@@ -74,18 +73,16 @@ from_tl1_trap:
        be,pn           %xcc, kvmap                     ! Yep, special processing
         CREATE_VPTE_OFFSET2(%g4, %g6)                  ! Create VPTE offset
        cmp             %g5, 4                          ! Last trap level?
-       be,pn           %xcc, longpath                  ! Yep, cannot risk VPTE miss
-        nop                                            ! delay slot
 
 /* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses        */
+       be,pn           %xcc, longpath                  ! Yep, cannot risk VPTE miss
+        nop                                            ! delay slot
        ldxa            [%g3 + %g6] ASI_S, %g5          ! Load VPTE
 1:     brgez,pn        %g5, longpath                   ! Invalid, branch out
         nop                                            ! Delay-slot
 9:     stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Reload TLB
        retry                                           ! Trap return
        nop
-       nop
-       nop
 
 /* DTLB ** ICACHE line 3: winfixups+real_faults                */
 longpath:
@@ -106,8 +103,7 @@ longpath:
        nop
        nop
        nop
-       CREATE_VPTE_NOP
+       nop
 
 #undef CREATE_VPTE_OFFSET1
 #undef CREATE_VPTE_OFFSET2
-#undef CREATE_VPTE_NOP
index d848bb7374bb4efe539e1e504c11339c5be993ae..e0a920162604e393dd8396e912b96c5d15a1bc12 100644 (file)
  */
 
 /* PROT ** ICACHE line 1: User DTLB protection trap    */
-       stxa            %g0, [%g1] ASI_DMMU             ! Clear SFSR FaultValid bit
-       membar          #Sync                           ! Synchronize ASI stores
-       rdpr            %pstate, %g5                    ! Move into alternate globals
+       mov             TLB_SFSR, %g1
+       stxa            %g0, [%g1] ASI_DMMU             ! Clear FaultValid bit
+       membar          #Sync                           ! Synchronize stores
+       rdpr            %pstate, %g5                    ! Move into alt-globals
        wrpr            %g5, PSTATE_AG|PSTATE_MG, %pstate
-       rdpr            %tl, %g1                        ! Need to do a winfixup?
+       rdpr            %tl, %g1                        ! Need a winfixup?
        cmp             %g1, 1                          ! Trap level >1?
-       mov             TLB_TAG_ACCESS, %g4             ! Prepare reload of vaddr
-       nop
+       mov             TLB_TAG_ACCESS, %g4             ! For reload of vaddr
 
 /* PROT ** ICACHE line 2: More real fault processing */
        bgu,pn          %xcc, winfix_trampoline         ! Yes, perform winfixup
index f1dcdf8f743390b044c603a65ad95cfc4b894e0a..b49dcd4504b029e1684730a554fe5cd0684dc92b 100644 (file)
 #include <asm/mmu.h>
        
 /* This section from from _start to sparc64_boot_end should fit into
- * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space
- * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
- * 0x0000.0000.0040.6000 and empty_bad_page, which is from
- * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000. 
+ * 0x0000000000404000 to 0x0000000000408000.
  */
-
        .text
        .globl  start, _start, stext, _stext
 _start:
 start:
 _stext:
 stext:
-bootup_user_stack:
 ! 0x0000000000404000
        b       sparc64_boot
         flushw                                 /* Flush register file.      */
@@ -191,8 +186,9 @@ prom_boot_mapping_phys_low:
        stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 5
        stx     %l2, [%sp + 2047 + 128 + 0x18]  ! arg1: "translate"
        stx     %l5, [%sp + 2047 + 128 + 0x20]  ! arg2: prom_mmu_ihandle_cache
-       srlx    %l0, 22, %l3
-       sllx    %l3, 22, %l3
+       /* PAGE align */
+       srlx    %l0, 13, %l3
+       sllx    %l3, 13, %l3
        stx     %l3, [%sp + 2047 + 128 + 0x28]  ! arg3: vaddr, our PC
        stx     %g0, [%sp + 2047 + 128 + 0x30]  ! res1
        stx     %g0, [%sp + 2047 + 128 + 0x38]  ! res2
@@ -211,6 +207,9 @@ prom_boot_mapping_phys_low:
        ldx     [%sp + 2047 + 128 + 0x48], %l2  ! physaddr high
        stx     %l2, [%l4 + 0x0]
        ldx     [%sp + 2047 + 128 + 0x50], %l3  ! physaddr low
+       /* 4MB align */
+       srlx    %l3, 22, %l3
+       sllx    %l3, 22, %l3
        stx     %l3, [%l4 + 0x8]
 
        /* Leave service as-is, "call-method" */
@@ -388,31 +387,30 @@ tlb_fixup_done:
         * former does use this code, the latter does not yet due
         * to some complexities.  That should be fixed up at some
         * point.
+        *
+        * There used to be enormous complexity wrt. transferring
+        * over from the firwmare's trap table to the Linux kernel's.
+        * For example, there was a chicken & egg problem wrt. building
+        * the OBP page tables, yet needing to be on the Linux kernel
+        * trap table (to translate PAGE_OFFSET addresses) in order to
+        * do that.
+        *
+        * We now handle OBP tlb misses differently, via linear lookups
+        * into the prom_trans[] array.  So that specific problem no
+        * longer exists.  Yet, unfortunately there are still some issues
+        * preventing trampoline.S from using this code... ho hum.
         */
        .globl  setup_trap_table
 setup_trap_table:
        save    %sp, -192, %sp
 
-       /* Force interrupts to be disabled.  Transferring over to
-        * the Linux trap table is a very delicate operation.
-        * Until we are actually on the Linux trap table, we cannot
-        * get the PAGE_OFFSET linear mappings translated.  We need
-        * that mapping to be setup in order to initialize the firmware
-        * page tables.
-        *
-        * So there is this window of time, from the return from
-        * prom_set_trap_table() until inherit_prom_mappings_post()
-        * (in arch/sparc64/mm/init.c) completes, during which no
-        * firmware address space accesses can be made.
-        */
+       /* Force interrupts to be disabled. */
        rdpr    %pstate, %o1
        andn    %o1, PSTATE_IE, %o1
        wrpr    %o1, 0x0, %pstate
        wrpr    %g0, 15, %pil
 
-       /* Ok, now make the final valid firmware call to jump over
-        * to the Linux trap table.
-        */
+       /* Make the firmware call to jump over to the Linux trap table.  */
        call    prom_set_trap_table
         sethi  %hi(sparc64_ttable_tl0), %o0
 
@@ -536,15 +534,21 @@ setup_tba:        /* i0 = is_starfire */
 
        ret
         restore
+sparc64_boot_end:
+
+#include "systbls.S"
+#include "ktlb.S"
+#include "etrap.S"
+#include "rtrap.S"
+#include "winfixup.S"
+#include "entry.S"
 
 /*
- * The following skips make sure the trap table in ttable.S is aligned
+ * The following skip makes sure the trap table in ttable.S is aligned
  * on a 32K boundary as required by the v9 specs for TBA register.
  */
-sparc64_boot_end:
-       .skip   0x2000 + _start - sparc64_boot_end
-bootup_user_stack_end:
-       .skip   0x2000
+1:
+       .skip   0x4000 + _start - 1b
 
 #ifdef CONFIG_SBUS
 /* This is just a hack to fool make depend config.h discovering
@@ -556,15 +560,6 @@ bootup_user_stack_end:
 ! 0x0000000000408000
 
 #include "ttable.S"
-#include "systbls.S"
-#include "ktlb.S"
-#include "etrap.S"
-#include "rtrap.S"
-#include "winfixup.S"
-#include "entry.S"
-
-       /* This is just anal retentiveness on my part... */
-       .align  16384
 
        .data
        .align  8
index b5e32dfa4fbc7bccc3a63c9726f85315f07e18a1..4951ff8f68775c52d46420bbeeee9df002614150 100644 (file)
  */
 #define CREATE_VPTE_OFFSET1(r1, r2) \
                                srax    r1, 10, r2
-#define CREATE_VPTE_OFFSET2(r1, r2)
-#define CREATE_VPTE_NOP                nop
+#define CREATE_VPTE_OFFSET2(r1, r2) nop
 #else /* PAGE_SHIFT */
 #define CREATE_VPTE_OFFSET1(r1, r2) \
                                srax    r1, PAGE_SHIFT, r2
 #define CREATE_VPTE_OFFSET2(r1, r2) \
                                sllx    r2, 3, r2
-#define CREATE_VPTE_NOP
 #endif /* PAGE_SHIFT */
 
 
@@ -36,6 +34,7 @@
  */
 
 /* ITLB ** ICACHE line 1: Quick user TLB misses                */
+       mov             TLB_SFSR, %g1
        ldxa            [%g1 + %g1] ASI_IMMU, %g4       ! Get TAG_ACCESS
        CREATE_VPTE_OFFSET1(%g4, %g6)                   ! Create VPTE offset
        CREATE_VPTE_OFFSET2(%g4, %g6)                   ! Create VPTE offset
 1:     brgez,pn        %g5, 3f                         ! Not valid, branch out
         sethi          %hi(_PAGE_EXEC), %g4            ! Delay-slot
        andcc           %g5, %g4, %g0                   ! Executable?
+
+/* ITLB ** ICACHE line 2: Real faults                  */
        be,pn           %xcc, 3f                        ! Nope, branch.
         nop                                            ! Delay-slot
 2:     stxa            %g5, [%g0] ASI_ITLB_DATA_IN     ! Load PTE into TLB
        retry                                           ! Trap return
-3:     rdpr            %pstate, %g4                    ! Move into alternate globals
-
-/* ITLB ** ICACHE line 2: Real faults                  */
+3:     rdpr            %pstate, %g4                    ! Move into alt-globals
        wrpr            %g4, PSTATE_AG|PSTATE_MG, %pstate
        rdpr            %tpc, %g5                       ! And load faulting VA
        mov             FAULT_CODE_ITLB, %g4            ! It was read from ITLB
-sparc64_realfault_common:                              ! Called by TL0 dtlb_miss too
+
+/* ITLB ** ICACHE line 3: Finish faults        */
+sparc64_realfault_common:                              ! Called by dtlb_miss
        stb             %g4, [%g6 + TI_FAULT_CODE]
        stx             %g5, [%g6 + TI_FAULT_ADDR]
        ba,pt           %xcc, etrap                     ! Save state
 1:      rd             %pc, %g7                        ! ...
-       nop
-
-/* ITLB ** ICACHE line 3: Finish faults + window fixups        */
        call            do_sparc64_fault                ! Call fault handler
         add            %sp, PTREGS_OFF, %o0! Compute pt_regs arg
        ba,pt           %xcc, rtrap_clr_l6              ! Restore cpu state
         nop
+
+/* ITLB ** ICACHE line 4: Window fixups */
 winfix_trampoline:
        rdpr            %tpc, %g3                       ! Prepare winfixup TNPC
-       or              %g3, 0x7c, %g3                  ! Compute offset to branch
+       or              %g3, 0x7c, %g3                  ! Compute branch offset
        wrpr            %g3, %tnpc                      ! Write it into TNPC
        done                                            ! Do it to it
-
-/* ITLB ** ICACHE line 4: Unused...    */
        nop
        nop
        nop
        nop
-       CREATE_VPTE_NOP
 
 #undef CREATE_VPTE_OFFSET1
 #undef CREATE_VPTE_OFFSET2
-#undef CREATE_VPTE_NOP
index 7796b37f478cc6c07806f7e920dabb60a1289db4..d9244d3c9f73dd9d47a9c08b95190afa9cee0e45 100644 (file)
@@ -58,9 +58,6 @@ vpte_noent:
        done
 
 vpte_insn_obp:
-       sethi           %hi(prom_pmd_phys), %g5
-       ldx             [%g5 + %lo(prom_pmd_phys)], %g5
-
        /* Behave as if we are at TL0.  */
        wrpr            %g0, 1, %tl
        rdpr            %tpc, %g4       /* Find original faulting iaddr */
@@ -71,58 +68,57 @@ vpte_insn_obp:
        mov             TLB_SFSR, %g1
        stxa            %g4, [%g1 + %g1] ASI_IMMU
 
-       /* Get PMD offset.  */
-       srlx            %g4, 23, %g6
-       and             %g6, 0x7ff, %g6
-       sllx            %g6, 2, %g6
-
-       /* Load PMD, is it valid?  */
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brz,pn          %g5, longpath
-        sllx           %g5, 11, %g5
-
-       /* Get PTE offset.  */
-       srlx            %g4, 13, %g6
-       and             %g6, 0x3ff, %g6
-       sllx            %g6, 3, %g6
-
-       /* Load PTE.  */
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brgez,pn        %g5, longpath
-        nop
-
-       /* TLB load and return from trap.  */
+       sethi           %hi(prom_trans), %g5
+       or              %g5, %lo(prom_trans), %g5
+
+1:     ldx             [%g5 + 0x00], %g6       ! base
+       brz,a,pn        %g6, longpath           ! no more entries, fail
+        mov            TLB_SFSR, %g1           ! and restore %g1
+       ldx             [%g5 + 0x08], %g1       ! len
+       add             %g6, %g1, %g1           ! end
+       cmp             %g6, %g4
+       bgu,pt          %xcc, 2f
+        cmp            %g4, %g1
+       bgeu,pt         %xcc, 2f
+        ldx            [%g5 + 0x10], %g1       ! PTE
+
+       /* TLB load, restore %g1, and return from trap.  */
+       sub             %g4, %g6, %g6
+       add             %g1, %g6, %g5
+       mov             TLB_SFSR, %g1
        stxa            %g5, [%g0] ASI_ITLB_DATA_IN
        retry
 
-kvmap_do_obp:
-       sethi           %hi(prom_pmd_phys), %g5
-       ldx             [%g5 + %lo(prom_pmd_phys)], %g5
-
-       /* Get PMD offset.  */
-       srlx            %g4, 23, %g6
-       and             %g6, 0x7ff, %g6
-       sllx            %g6, 2, %g6
-
-       /* Load PMD, is it valid?  */
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brz,pn          %g5, longpath
-        sllx           %g5, 11, %g5
-
-       /* Get PTE offset.  */
-       srlx            %g4, 13, %g6
-       and             %g6, 0x3ff, %g6
-       sllx            %g6, 3, %g6
-
-       /* Load PTE.  */
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brgez,pn        %g5, longpath
-        nop
+2:     ba,pt           %xcc, 1b
+        add            %g5, (3 * 8), %g5       ! next entry
 
-       /* TLB load and return from trap.  */
+kvmap_do_obp:
+       sethi           %hi(prom_trans), %g5
+       or              %g5, %lo(prom_trans), %g5
+       srlx            %g4, 13, %g4
+       sllx            %g4, 13, %g4
+
+1:     ldx             [%g5 + 0x00], %g6       ! base
+       brz,a,pn        %g6, longpath           ! no more entries, fail
+        mov            TLB_SFSR, %g1           ! and restore %g1
+       ldx             [%g5 + 0x08], %g1       ! len
+       add             %g6, %g1, %g1           ! end
+       cmp             %g6, %g4
+       bgu,pt          %xcc, 2f
+        cmp            %g4, %g1
+       bgeu,pt         %xcc, 2f
+        ldx            [%g5 + 0x10], %g1       ! PTE
+
+       /* TLB load, restore %g1, and return from trap.  */
+       sub             %g4, %g6, %g6
+       add             %g1, %g6, %g5
+       mov             TLB_SFSR, %g1
        stxa            %g5, [%g0] ASI_DTLB_DATA_IN
        retry
 
+2:     ba,pt           %xcc, 1b
+        add            %g5, (3 * 8), %g5       ! next entry
+
 /*
  * On a first level data miss, check whether this is to the OBP range (note
  * that such accesses can be made by prom, as well as by kernel using
index 0d2e967c7200b3eedb3a64879fc2b6703594ec23..1e44ee26cee8470d8bfc97e0ddb9c29f01383e5c 100644 (file)
@@ -105,7 +105,7 @@ static void __init read_obp_memory(const char *property,
                regs[i].phys_addr = base;
                regs[i].reg_size = size;
        }
-       sort(regs, ents, sizeof(struct  linux_prom64_registers),
+       sort(regs, ents, sizeof(struct linux_prom64_registers),
             cmp_p64, NULL);
 }
 
@@ -367,8 +367,11 @@ struct linux_prom_translation {
        unsigned long size;
        unsigned long data;
 };
-static struct linux_prom_translation prom_trans[512] __initdata;
-static unsigned int prom_trans_ents __initdata;
+
+/* Exported for kernel TLB miss handling in ktlb.S */
+struct linux_prom_translation prom_trans[512] __read_mostly;
+unsigned int prom_trans_ents __read_mostly;
+unsigned int swapper_pgd_zero __read_mostly;
 
 extern unsigned long prom_boot_page;
 extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
@@ -378,122 +381,57 @@ extern void register_prom_callbacks(void);
 /* Exported for SMP bootup purposes. */
 unsigned long kern_locked_tte_data;
 
-/* Exported for kernel TLB miss handling in ktlb.S */
-unsigned long prom_pmd_phys __read_mostly;
-unsigned int swapper_pgd_zero __read_mostly;
-
-static pmd_t *prompmd __read_mostly;
-
-#define BASE_PAGE_SIZE 8192
-
 /*
  * Translate PROM's mapping we capture at boot time into physical address.
  * The second parameter is only set from prom_callback() invocations.
  */
 unsigned long prom_virt_to_phys(unsigned long promva, int *error)
 {
-       pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff);
-       pte_t *ptep;
-       unsigned long base;
-
-       if (pmd_none(*pmdp)) {
-               if (error)
-                       *error = 1;
-               return 0;
-       }
-       ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
-       if (!pte_present(*ptep)) {
-               if (error)
-                       *error = 1;
-               return 0;
-       }
-       if (error) {
-               *error = 0;
-               return pte_val(*ptep);
-       }
-       base = pte_val(*ptep) & _PAGE_PADDR;
-
-       return base + (promva & (BASE_PAGE_SIZE - 1));
-}
+       int i;
 
-/* The obp translations are saved based on 8k pagesize, since obp can
- * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS ->
- * HI_OBP_ADDRESS range are handled in entry.S and do not use the vpte
- * scheme (also, see rant in inherit_locked_prom_mappings()).
- */
-static void __init build_obp_range(unsigned long start, unsigned long end, unsigned long data)
-{
-       unsigned long vaddr;
+       for (i = 0; i < prom_trans_ents; i++) {
+               struct linux_prom_translation *p = &prom_trans[i];
 
-       for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) {
-               unsigned long val;
-               pmd_t *pmd;
-               pte_t *pte;
+               if (promva >= p->virt &&
+                   promva < (p->virt + p->size)) {
+                       unsigned long base = p->data & _PAGE_PADDR;
 
-               pmd = prompmd + ((vaddr >> 23) & 0x7ff);
-               if (pmd_none(*pmd)) {
-                       pte = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE,
-                                             PAGE_SIZE);
-                       if (!pte)
-                               prom_halt();
-                       memset(pte, 0, BASE_PAGE_SIZE);
-                       pmd_set(pmd, pte);
+                       if (error)
+                               *error = 0;
+                       return base + (promva & (8192 - 1));
                }
-               pte = (pte_t *) __pmd_page(*pmd) + ((vaddr >> 13) & 0x3ff);
-
-               val = data;
-
-               /* Clear diag TTE bits. */
-               if (tlb_type == spitfire)
-                       val &= ~0x0003fe0000000000UL;
-
-               set_pte_at(&init_mm, vaddr, pte,
-                          __pte(val | _PAGE_MODIFIED));
-
-               data += BASE_PAGE_SIZE;
        }
+       if (error)
+               *error = 1;
+       return 0UL;
 }
 
+/* The obp translations are saved based on 8k pagesize, since obp can
+ * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS ->
+ * HI_OBP_ADDRESS range are handled in ktlb.S and do not use the vpte
+ * scheme (also, see rant in inherit_locked_prom_mappings()).
+ */
 static inline int in_obp_range(unsigned long vaddr)
 {
        return (vaddr >= LOW_OBP_ADDRESS &&
                vaddr < HI_OBP_ADDRESS);
 }
 
-#define OBP_PMD_SIZE 2048
-static void __init build_obp_pgtable(void)
+static int cmp_ptrans(const void *a, const void *b)
 {
-       unsigned long i;
-
-       prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, PAGE_SIZE);
-       if (!prompmd)
-               prom_halt();
-
-       memset(prompmd, 0, OBP_PMD_SIZE);
-
-       prom_pmd_phys = __pa(prompmd);
-
-       for (i = 0; i < prom_trans_ents; i++) {
-               unsigned long start, end;
-
-               if (!in_obp_range(prom_trans[i].virt))
-                       continue;
+       const struct linux_prom_translation *x = a, *y = b;
 
-               start = prom_trans[i].virt;
-               end = start + prom_trans[i].size;
-               if (end > HI_OBP_ADDRESS)
-                       end = HI_OBP_ADDRESS;
-
-               build_obp_range(start, end, prom_trans[i].data);
-       }
+       if (x->virt > y->virt)
+               return 1;
+       if (x->virt < y->virt)
+               return -1;
+       return 0;
 }
 
-/* Read OBP translations property into 'prom_trans[]'.
- * Return the number of entries.
- */
+/* Read OBP translations property into 'prom_trans[]'.  */
 static void __init read_obp_translations(void)
 {
-       int n, node;
+       int n, node, ents, first, last, i;
 
        node = prom_finddevice("/virtual-memory");
        n = prom_getproplen(node, "translations");
@@ -515,7 +453,41 @@ static void __init read_obp_translations(void)
 
        n = n / sizeof(struct linux_prom_translation);
 
-       prom_trans_ents = n;
+       ents = n;
+
+       sort(prom_trans, ents, sizeof(struct linux_prom_translation),
+            cmp_ptrans, NULL);
+
+       /* Now kick out all the non-OBP entries.  */
+       for (i = 0; i < ents; i++) {
+               if (in_obp_range(prom_trans[i].virt))
+                       break;
+       }
+       first = i;
+       for (; i < ents; i++) {
+               if (!in_obp_range(prom_trans[i].virt))
+                       break;
+       }
+       last = i;
+
+       for (i = 0; i < (last - first); i++) {
+               struct linux_prom_translation *src = &prom_trans[i + first];
+               struct linux_prom_translation *dest = &prom_trans[i];
+
+               *dest = *src;
+       }
+       for (; i < ents; i++) {
+               struct linux_prom_translation *dest = &prom_trans[i];
+               dest->virt = dest->size = dest->data = 0x0UL;
+       }
+
+       prom_trans_ents = last - first;
+
+       if (tlb_type == spitfire) {
+               /* Clear diag TTE bits. */
+               for (i = 0; i < prom_trans_ents; i++)
+                       prom_trans[i].data &= ~0x0003fe0000000000UL;
+       }
 }
 
 static void __init remap_kernel(void)
@@ -553,21 +525,18 @@ static void __init remap_kernel(void)
 }
 
 
-static void __init inherit_prom_mappings_pre(void)
+static void __init inherit_prom_mappings(void)
 {
        read_obp_translations();
 
        /* Now fixup OBP's idea about where we really are mapped. */
        prom_printf("Remapping the kernel... ");
        remap_kernel();
-
        prom_printf("done.\n");
-}
 
-static void __init inherit_prom_mappings_post(void)
-{
-       build_obp_pgtable();
+       prom_printf("Registering callbacks... ");
        register_prom_callbacks();
+       prom_printf("done.\n");
 }
 
 /* The OBP specifications for sun4u mark 0xfffffffc00000000 and
@@ -1519,7 +1488,7 @@ void __init paging_init(void)
        
        swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
        
-       inherit_prom_mappings_pre();
+       inherit_prom_mappings();
        
        /* Ok, we can use our TLB miss and window trap handlers safely.
         * We need to do a quick peek here to see if we are on StarFire
@@ -1530,23 +1499,15 @@ void __init paging_init(void)
                extern void setup_tba(int);
                setup_tba(this_is_starfire);
        }
-       __flush_tlb_all();
 
-       /* Everything from this point forward, until we are done with
-        * inherit_prom_mappings_post(), must complete successfully
-        * without calling into the firmware.  The firwmare page tables
-        * have not been built, but we are running on the Linux kernel's
-        * trap table.
-        */
+       inherit_locked_prom_mappings(1);
+
+       __flush_tlb_all();
 
        /* Setup bootmem... */
        pages_avail = 0;
        last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
 
-       inherit_prom_mappings_post();
-
-       inherit_locked_prom_mappings(1);
-
 #ifdef CONFIG_DEBUG_PAGEALLOC
        kernel_physical_mapping_init();
 #endif
index 783e18cae090ec1d1c77e0cafc05cfd5fa703608..de17d4c6e02db13309752ca26a99c2536f5f0163 100644 (file)
@@ -13,7 +13,7 @@ mcast-objs := mcast_kern.o mcast_user.o
 net-objs := net_kern.o net_user.o
 mconsole-objs := mconsole_kern.o mconsole_user.o
 hostaudio-objs := hostaudio_kern.o
-ubd-objs := ubd_kern.o
+ubd-objs := ubd_kern.o ubd_user.o
 port-objs := port_kern.o port_user.o
 harddog-objs := harddog_kern.o harddog_user.o
 
index e77a38da4350d6b4abdccfd3cab1c1d5755c3864..f73134333f64ee55c9eb7f87521e89f577400297 100644 (file)
@@ -35,7 +35,6 @@
 #include "linux/blkpg.h"
 #include "linux/genhd.h"
 #include "linux/spinlock.h"
-#include "asm/atomic.h"
 #include "asm/segment.h"
 #include "asm/uaccess.h"
 #include "asm/irq.h"
 #include "mem.h"
 #include "mem_kern.h"
 #include "cow.h"
-#include "aio.h"
 
 enum ubd_req { UBD_READ, UBD_WRITE };
 
 struct io_thread_req {
-       enum aio_type op;
+       enum ubd_req op;
        int fds[2];
        unsigned long offsets[2];
        unsigned long long offset;
        unsigned long length;
        char *buffer;
        int sectorsize;
-       int bitmap_offset;
-       long bitmap_start;
-       long bitmap_end;
+       unsigned long sector_mask;
+       unsigned long long cow_offset;
+       unsigned long bitmap_words[2];
        int error;
 };
 
@@ -82,31 +80,28 @@ extern int create_cow_file(char *cow_file, char *backing_file,
                           unsigned long *bitmap_len_out,
                           int *data_offset_out);
 extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
-extern void do_io(struct io_thread_req *req, struct request *r,
-                 unsigned long *bitmap);
+extern void do_io(struct io_thread_req *req);
 
-static inline int ubd_test_bit(__u64 bit, void *data)
+static inline int ubd_test_bit(__u64 bit, unsigned char *data)
 {
-       unsigned char *buffer = data;
        __u64 n;
        int bits, off;
 
-       bits = sizeof(buffer[0]) * 8;
+       bits = sizeof(data[0]) * 8;
        n = bit / bits;
        off = bit % bits;
-       return((buffer[n] & (1 << off)) != 0);
+       return((data[n] & (1 << off)) != 0);
 }
 
-static inline void ubd_set_bit(__u64 bit, void *data)
+static inline void ubd_set_bit(__u64 bit, unsigned char *data)
 {
-       unsigned char *buffer = data;
        __u64 n;
        int bits, off;
 
-       bits = sizeof(buffer[0]) * 8;
+       bits = sizeof(data[0]) * 8;
        n = bit / bits;
        off = bit % bits;
-       buffer[n] |= (1 << off);
+       data[n] |= (1 << off);
 }
 /*End stuff from ubd_user.h*/
 
@@ -115,6 +110,8 @@ static inline void ubd_set_bit(__u64 bit, void *data)
 static DEFINE_SPINLOCK(ubd_io_lock);
 static DEFINE_SPINLOCK(ubd_lock);
 
+static void (*do_ubd)(void);
+
 static int ubd_open(struct inode * inode, struct file * filp);
 static int ubd_release(struct inode * inode, struct file * file);
 static int ubd_ioctl(struct inode * inode, struct file * file,
@@ -161,8 +158,6 @@ struct cow {
         int data_offset;
 };
 
-#define MAX_SG 64
-
 struct ubd {
        char *file;
        int count;
@@ -173,7 +168,6 @@ struct ubd {
        int no_cow;
        struct cow cow;
        struct platform_device pdev;
-        struct scatterlist sg[MAX_SG];
 };
 
 #define DEFAULT_COW { \
@@ -466,114 +460,81 @@ __uml_help(fakehd,
 );
 
 static void do_ubd_request(request_queue_t * q);
-static int in_ubd;
+
+/* Only changed by ubd_init, which is an initcall. */
+int thread_fd = -1;
 
 /* Changed by ubd_handler, which is serialized because interrupts only
  * happen on CPU 0.
  */
 int intr_count = 0;
 
-static void ubd_end_request(struct request *req, int bytes, int uptodate)
+/* call ubd_finish if you need to serialize */
+static void __ubd_finish(struct request *req, int error)
 {
-       if (!end_that_request_first(req, uptodate, bytes >> 9)) {
-               add_disk_randomness(req->rq_disk);
-               end_that_request_last(req);
+       int nsect;
+
+       if(error){
+               end_request(req, 0);
+               return;
        }
+       nsect = req->current_nr_sectors;
+       req->sector += nsect;
+       req->buffer += nsect << 9;
+       req->errors = 0;
+       req->nr_sectors -= nsect;
+       req->current_nr_sectors = 0;
+       end_request(req, 1);
 }
 
-/* call ubd_finish if you need to serialize */
-static void __ubd_finish(struct request *req, int bytes)
+static inline void ubd_finish(struct request *req, int error)
 {
-       if(bytes < 0){
-               ubd_end_request(req, 0, 0);
-               return;
-       }
-
-       ubd_end_request(req, bytes, 1);
+       spin_lock(&ubd_io_lock);
+       __ubd_finish(req, error);
+       spin_unlock(&ubd_io_lock);
 }
 
-static inline void ubd_finish(struct request *req, int bytes)
+/* Called without ubd_io_lock held */
+static void ubd_handler(void)
 {
-       spin_lock(&ubd_io_lock);
-       __ubd_finish(req, bytes);
-       spin_unlock(&ubd_io_lock);
+       struct io_thread_req req;
+       struct request *rq = elv_next_request(ubd_queue);
+       int n;
+
+       do_ubd = NULL;
+       intr_count++;
+       n = os_read_file(thread_fd, &req, sizeof(req));
+       if(n != sizeof(req)){
+               printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
+                      "err = %d\n", os_getpid(), -n);
+               spin_lock(&ubd_io_lock);
+               end_request(rq, 0);
+               spin_unlock(&ubd_io_lock);
+               return;
+       }
+        
+       ubd_finish(rq, req.error);
+       reactivate_fd(thread_fd, UBD_IRQ);      
+       do_ubd_request(ubd_queue);
 }
 
-struct bitmap_io {
-        atomic_t count;
-        struct aio_context aio;
-};
-
-struct ubd_aio {
-        struct aio_context aio;
-        struct request *req;
-        int len;
-        struct bitmap_io *bitmap;
-        void *bitmap_buf;
-};
-
-static int ubd_reply_fd = -1;
-
 static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
 {
-       struct aio_thread_reply reply;
-       struct ubd_aio *aio;
-       struct request *req;
-       int err, n, fd = (int) (long) dev;
-
-       while(1){
-               err = os_read_file(fd, &reply, sizeof(reply));
-               if(err == -EAGAIN)
-                       break;
-               if(err < 0){
-                       printk("ubd_aio_handler - read returned err %d\n",
-                              -err);
-                       break;
-               }
-
-                aio = container_of(reply.data, struct ubd_aio, aio);
-                n = reply.err;
-
-               if(n == 0){
-                       req = aio->req;
-                       req->nr_sectors -= aio->len >> 9;
-
-                       if((aio->bitmap != NULL) &&
-                          (atomic_dec_and_test(&aio->bitmap->count))){
-                                aio->aio = aio->bitmap->aio;
-                                aio->len = 0;
-                                kfree(aio->bitmap);
-                                aio->bitmap = NULL;
-                                submit_aio(&aio->aio);
-                       }
-                       else {
-                               if((req->nr_sectors == 0) &&
-                                   (aio->bitmap == NULL)){
-                                       int len = req->hard_nr_sectors << 9;
-                                       ubd_finish(req, len);
-                               }
-
-                                if(aio->bitmap_buf != NULL)
-                                        kfree(aio->bitmap_buf);
-                               kfree(aio);
-                       }
-               }
-                else if(n < 0){
-                        ubd_finish(aio->req, n);
-                        if(aio->bitmap != NULL)
-                                kfree(aio->bitmap);
-                        if(aio->bitmap_buf != NULL)
-                                kfree(aio->bitmap_buf);
-                        kfree(aio);
-                }
-       }
-       reactivate_fd(fd, UBD_IRQ);
+       ubd_handler();
+       return(IRQ_HANDLED);
+}
 
-        do_ubd_request(ubd_queue);
+/* Only changed by ubd_init, which is an initcall. */
+static int io_pid = -1;
 
-       return(IRQ_HANDLED);
+void kill_io_thread(void)
+{
+       if(io_pid != -1) 
+               os_kill_process(io_pid, 1);
 }
 
+__uml_exitcall(kill_io_thread);
+
 static int ubd_file_size(struct ubd *dev, __u64 *size_out)
 {
        char *file;
@@ -608,7 +569,7 @@ static int ubd_open_dev(struct ubd *dev)
                                &dev->cow.data_offset, create_ptr);
 
        if((dev->fd == -ENOENT) && create_cow){
-               dev->fd = create_cow_file(dev->file, dev->cow.file,
+               dev->fd = create_cow_file(dev->file, dev->cow.file, 
                                          dev->openflags, 1 << 9, PAGE_SIZE,
                                          &dev->cow.bitmap_offset, 
                                          &dev->cow.bitmap_len,
@@ -870,10 +831,6 @@ int ubd_init(void)
 {
         int i;
 
-       ubd_reply_fd = init_aio_irq(UBD_IRQ, "ubd", ubd_intr);
-       if(ubd_reply_fd < 0)
-               printk("Setting up ubd AIO failed, err = %d\n", ubd_reply_fd);
-
        devfs_mk_dir("ubd");
        if (register_blkdev(MAJOR_NR, "ubd"))
                return -1;
@@ -884,7 +841,6 @@ int ubd_init(void)
                return -1;
        }
                
-       blk_queue_max_hw_segments(ubd_queue, MAX_SG);
        if (fake_major != MAJOR_NR) {
                char name[sizeof("ubd_nnn\0")];
 
@@ -896,12 +852,40 @@ int ubd_init(void)
        driver_register(&ubd_driver);
        for (i = 0; i < MAX_DEV; i++) 
                ubd_add(i);
-
        return 0;
 }
 
 late_initcall(ubd_init);
 
+int ubd_driver_init(void){
+       unsigned long stack;
+       int err;
+
+       /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
+       if(global_openflags.s){
+               printk(KERN_INFO "ubd: Synchronous mode\n");
+               /* Letting ubd=sync be like using ubd#s= instead of ubd#= is
+                * enough. So use anyway the io thread. */
+       }
+       stack = alloc_stack(0, 0);
+       io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), 
+                                &thread_fd);
+       if(io_pid < 0){
+               printk(KERN_ERR 
+                      "ubd : Failed to start I/O thread (errno = %d) - "
+                      "falling back to synchronous I/O\n", -io_pid);
+               io_pid = -1;
+               return(0);
+       }
+       err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, 
+                            SA_INTERRUPT, "ubd", ubd_dev);
+       if(err != 0)
+               printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
+       return(err);
+}
+
+device_initcall(ubd_driver_init);
+
 static int ubd_open(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
@@ -939,55 +923,105 @@ static int ubd_release(struct inode * inode, struct file * file)
        return(0);
 }
 
-static void cowify_bitmap(struct io_thread_req *req, unsigned long *bitmap)
+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
+                         __u64 *cow_offset, unsigned long *bitmap,
+                         __u64 bitmap_offset, unsigned long *bitmap_words,
+                         __u64 bitmap_len)
 {
-        __u64 sector = req->offset / req->sectorsize;
-        int i;
+       __u64 sector = io_offset >> 9;
+       int i, update_bitmap = 0;
+
+       for(i = 0; i < length >> 9; i++){
+               if(cow_mask != NULL)
+                       ubd_set_bit(i, (unsigned char *) cow_mask);
+               if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+                       continue;
 
-        for(i = 0; i < req->length / req->sectorsize; i++){
-                if(ubd_test_bit(sector + i, bitmap))
-                        continue;
+               update_bitmap = 1;
+               ubd_set_bit(sector + i, (unsigned char *) bitmap);
+       }
+
+       if(!update_bitmap)
+               return;
 
-                if(req->bitmap_start == -1)
-                        req->bitmap_start = sector + i;
-                req->bitmap_end = sector + i + 1;
+       *cow_offset = sector / (sizeof(unsigned long) * 8);
 
-                ubd_set_bit(sector + i, bitmap);
-        }
+       /* This takes care of the case where we're exactly at the end of the
+        * device, and *cow_offset + 1 is off the end.  So, just back it up
+        * by one word.  Thanks to Lynn Kerby for the fix and James McMechan
+        * for the original diagnosis.
+        */
+       if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
+                          sizeof(unsigned long) - 1))
+               (*cow_offset)--;
+
+       bitmap_words[0] = bitmap[*cow_offset];
+       bitmap_words[1] = bitmap[*cow_offset + 1];
+
+       *cow_offset *= sizeof(unsigned long);
+       *cow_offset += bitmap_offset;
+}
+
+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
+                      __u64 bitmap_offset, __u64 bitmap_len)
+{
+       __u64 sector = req->offset >> 9;
+       int i;
+
+       if(req->length > (sizeof(req->sector_mask) * 8) << 9)
+               panic("Operation too long");
+
+       if(req->op == UBD_READ) {
+               for(i = 0; i < req->length >> 9; i++){
+                       if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+                               ubd_set_bit(i, (unsigned char *) 
+                                           &req->sector_mask);
+                }
+       }
+       else cowify_bitmap(req->offset, req->length, &req->sector_mask,
+                          &req->cow_offset, bitmap, bitmap_offset,
+                          req->bitmap_words, bitmap_len);
 }
 
 /* Called with ubd_io_lock held */
-static int prepare_request(struct request *req, struct io_thread_req *io_req,
-                           unsigned long long offset, int page_offset,
-                           int len, struct page *page)
+static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
        struct gendisk *disk = req->rq_disk;
        struct ubd *dev = disk->private_data;
+       __u64 offset;
+       int len;
+
+       if(req->rq_status == RQ_INACTIVE) return(1);
 
        /* This should be impossible now */
        if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
                printk("Write attempted on readonly ubd device %s\n", 
                       disk->disk_name);
-                ubd_end_request(req, 0, 0);
+               end_request(req, 0);
                return(1);
        }
 
+       offset = ((__u64) req->sector) << 9;
+       len = req->current_nr_sectors << 9;
+
        io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
        io_req->fds[1] = dev->fd;
+       io_req->cow_offset = -1;
        io_req->offset = offset;
        io_req->length = len;
        io_req->error = 0;
-       io_req->op = (rq_data_dir(req) == READ) ? AIO_READ : AIO_WRITE;
+       io_req->sector_mask = 0;
+
+       io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
        io_req->offsets[0] = 0;
        io_req->offsets[1] = dev->cow.data_offset;
-        io_req->buffer = page_address(page) + page_offset;
+       io_req->buffer = req->buffer;
        io_req->sectorsize = 1 << 9;
-        io_req->bitmap_offset = dev->cow.bitmap_offset;
-        io_req->bitmap_start = -1;
-        io_req->bitmap_end = -1;
 
-        if((dev->cow.file != NULL) && (io_req->op == UBD_WRITE))
-                cowify_bitmap(io_req, dev->cow.bitmap);
+       if(dev->cow.file != NULL)
+               cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
+                          dev->cow.bitmap_len);
+
        return(0);
 }
 
@@ -996,36 +1030,30 @@ static void do_ubd_request(request_queue_t *q)
 {
        struct io_thread_req io_req;
        struct request *req;
-       __u64 sector;
-       int err;
-
-       if(in_ubd)
-               return;
-       in_ubd = 1;
-       while((req = elv_next_request(q)) != NULL){
-               struct gendisk *disk = req->rq_disk;
-               struct ubd *dev = disk->private_data;
-               int n, i;
-
-               blkdev_dequeue_request(req);
-
-               sector = req->sector;
-               n = blk_rq_map_sg(q, req, dev->sg);
-
-               for(i = 0; i < n; i++){
-                       struct scatterlist *sg = &dev->sg[i];
-
-                       err = prepare_request(req, &io_req, sector << 9,
-                                             sg->offset, sg->length,
-                                             sg->page);
-                       if(err)
-                               continue;
-
-                       sector += sg->length >> 9;
-                       do_io(&io_req, req, dev->cow.bitmap);
+       int err, n;
+
+       if(thread_fd == -1){
+               while((req = elv_next_request(q)) != NULL){
+                       err = prepare_request(req, &io_req);
+                       if(!err){
+                               do_io(&io_req);
+                               __ubd_finish(req, io_req.error);
+                       }
+               }
+       }
+       else {
+               if(do_ubd || (req = elv_next_request(q)) == NULL)
+                       return;
+               err = prepare_request(req, &io_req);
+               if(!err){
+                       do_ubd = ubd_handler;
+                       n = os_write_file(thread_fd, (char *) &io_req,
+                                        sizeof(io_req));
+                       if(n != sizeof(io_req))
+                               printk("write to io thread failed, "
+                                      "errno = %d\n", -n);
                }
        }
-       in_ubd = 0;
 }
 
 static int ubd_ioctl(struct inode * inode, struct file * file,
@@ -1241,95 +1269,131 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
        return(err);
 }
 
-void do_io(struct io_thread_req *req, struct request *r, unsigned long *bitmap)
+static int update_bitmap(struct io_thread_req *req)
 {
-        struct ubd_aio *aio;
-        struct bitmap_io *bitmap_io = NULL;
-        char *buf;
-        void *bitmap_buf = NULL;
-        unsigned long len, sector;
-        int nsectors, start, end, bit, err;
-        __u64 off;
-
-        if(req->bitmap_start != -1){
-                /* Round up to the nearest word */
-                int round = sizeof(unsigned long);
-                len = (req->bitmap_end - req->bitmap_start +
-                       round * 8 - 1) / (round * 8);
-                len *= round;
-
-                off = req->bitmap_start / (8 * round);
-                off *= round;
-
-                bitmap_io = kmalloc(sizeof(*bitmap_io), GFP_KERNEL);
-                if(bitmap_io == NULL){
-                        printk("Failed to kmalloc bitmap IO\n");
-                        req->error = 1;
-                        return;
-                }
+       int n;
 
-                bitmap_buf = kmalloc(len, GFP_KERNEL);
-                if(bitmap_buf == NULL){
-                        printk("do_io : kmalloc of bitmap chunk "
-                               "failed\n");
-                        kfree(bitmap_io);
-                        req->error = 1;
-                        return;
-                }
-                memcpy(bitmap_buf, &bitmap[off / sizeof(bitmap[0])], len);
-
-                *bitmap_io = ((struct bitmap_io)
-                        { .count       = ATOMIC_INIT(0),
-                          .aio         = INIT_AIO(AIO_WRITE, req->fds[1],
-                                                   bitmap_buf, len,
-                                                   req->bitmap_offset + off,
-                                                   ubd_reply_fd) } );
-        }
+       if(req->cow_offset == -1)
+               return(0);
 
-        nsectors = req->length / req->sectorsize;
-        start = 0;
-        end = nsectors;
-        bit = 0;
-        do {
-                if(bitmap != NULL){
-                        sector = req->offset / req->sectorsize;
-                        bit = ubd_test_bit(sector + start, bitmap);
-                        end = start;
-                        while((end < nsectors) &&
-                              (ubd_test_bit(sector + end, bitmap) == bit))
-                                end++;
-                }
+       n = os_seek_file(req->fds[1], req->cow_offset);
+       if(n < 0){
+               printk("do_io - bitmap lseek failed : err = %d\n", -n);
+               return(1);
+       }
 
-                off = req->offsets[bit] + req->offset +
-                        start * req->sectorsize;
-                len = (end - start) * req->sectorsize;
-                buf = &req->buffer[start * req->sectorsize];
+       n = os_write_file(req->fds[1], &req->bitmap_words,
+                         sizeof(req->bitmap_words));
+       if(n != sizeof(req->bitmap_words)){
+               printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
+                      req->fds[1]);
+               return(1);
+       }
 
-                aio = kmalloc(sizeof(*aio), GFP_KERNEL);
-                if(aio == NULL){
-                        req->error = 1;
-                        return;
-                }
+       return(0);
+}
 
-                *aio = ((struct ubd_aio)
-                        { .aio         = INIT_AIO(req->op, req->fds[bit], buf,
-                                                   len, off, ubd_reply_fd),
-                          .len         = len,
-                          .req         = r,
-                          .bitmap      = bitmap_io,
-                          .bitmap_buf  = bitmap_buf });
-
-                if(aio->bitmap != NULL)
-                        atomic_inc(&aio->bitmap->count);
-
-                err = submit_aio(&aio->aio);
-                if(err){
-                        printk("do_io - submit_aio failed, "
-                               "err = %d\n", err);
-                        req->error = 1;
-                        return;
-                }
+void do_io(struct io_thread_req *req)
+{
+       char *buf;
+       unsigned long len;
+       int n, nsectors, start, end, bit;
+       int err;
+       __u64 off;
+
+       nsectors = req->length / req->sectorsize;
+       start = 0;
+       do {
+               bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
+               end = start;
+               while((end < nsectors) &&
+                     (ubd_test_bit(end, (unsigned char *)
+                                   &req->sector_mask) == bit))
+                       end++;
+
+               off = req->offset + req->offsets[bit] +
+                       start * req->sectorsize;
+               len = (end - start) * req->sectorsize;
+               buf = &req->buffer[start * req->sectorsize];
+
+               err = os_seek_file(req->fds[bit], off);
+               if(err < 0){
+                       printk("do_io - lseek failed : err = %d\n", -err);
+                       req->error = 1;
+                       return;
+               }
+               if(req->op == UBD_READ){
+                       n = 0;
+                       do {
+                               buf = &buf[n];
+                               len -= n;
+                               n = os_read_file(req->fds[bit], buf, len);
+                               if (n < 0) {
+                                       printk("do_io - read failed, err = %d "
+                                              "fd = %d\n", -n, req->fds[bit]);
+                                       req->error = 1;
+                                       return;
+                               }
+                       } while((n < len) && (n != 0));
+                       if (n < len) memset(&buf[n], 0, len - n);
+               } else {
+                       n = os_write_file(req->fds[bit], buf, len);
+                       if(n != len){
+                               printk("do_io - write failed err = %d "
+                                      "fd = %d\n", -n, req->fds[bit]);
+                               req->error = 1;
+                               return;
+                       }
+               }
+
+               start = end;
+       } while(start < nsectors);
 
-                start = end;
-        } while(start < nsectors);
+       req->error = update_bitmap(req);
 }
+
+/* Changed in start_io_thread, which is serialized by being called only
+ * from ubd_init, which is an initcall.
+ */
+int kernel_fd = -1;
+
+/* Only changed by the io thread */
+int io_count = 0;
+
+int io_thread(void *arg)
+{
+       struct io_thread_req req;
+       int n;
+
+       ignore_sigwinch_sig();
+       while(1){
+               n = os_read_file(kernel_fd, &req, sizeof(req));
+               if(n != sizeof(req)){
+                       if(n < 0)
+                               printk("io_thread - read failed, fd = %d, "
+                                      "err = %d\n", kernel_fd, -n);
+                       else {
+                               printk("io_thread - short read, fd = %d, "
+                                      "length = %d\n", kernel_fd, n);
+                       }
+                       continue;
+               }
+               io_count++;
+               do_io(&req);
+               n = os_write_file(kernel_fd, &req, sizeof(req));
+               if(n != sizeof(req))
+                       printk("io_thread - write failed, fd = %d, err = %d\n",
+                              kernel_fd, -n);
+       }
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
new file mode 100644 (file)
index 0000000..b94d2bc
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
+ * Licensed under the GPL
+ */
+
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include "asm/types.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "ubd_user.h"
+#include "os.h"
+#include "cow.h"
+
+#include <endian.h>
+#include <byteswap.h>
+
+void ignore_sigwinch_sig(void)
+{
+       signal(SIGWINCH, SIG_IGN);
+}
+
+int start_io_thread(unsigned long sp, int *fd_out)
+{
+       int pid, fds[2], err;
+
+       err = os_pipe(fds, 1, 1);
+       if(err < 0){
+               printk("start_io_thread - os_pipe failed, err = %d\n", -err);
+               goto out;
+       }
+
+       kernel_fd = fds[0];
+       *fd_out = fds[1];
+
+       pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
+                   NULL);
+       if(pid < 0){
+               printk("start_io_thread - clone failed : errno = %d\n", errno);
+               err = -errno;
+               goto out_close;
+       }
+
+       return(pid);
+
+ out_close:
+       os_close_file(fds[0]);
+       os_close_file(fds[1]);
+       kernel_fd = -1;
+       *fd_out = -1;
+ out:
+       return(err);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
index 83f16877ab0828baf413d5e0025fe2b1965c23db..423bae9153f8adf359330a94321cfc6ab89ee422 100644 (file)
@@ -14,27 +14,15 @@ struct aio_thread_reply {
 };
 
 struct aio_context {
-       enum aio_type type;
-       int fd;
-       void *data;
-       int len;
-       unsigned long long offset;
        int reply_fd;
        struct aio_context *next;
 };
 
-#define INIT_AIO(aio_type, aio_fd, aio_data, aio_len, aio_offset, \
-                aio_reply_fd) \
-       { .type         = aio_type, \
-         .fd           = aio_fd, \
-         .data         = aio_data, \
-         .len          = aio_len, \
-         .offset       = aio_offset, \
-         .reply_fd     = aio_reply_fd }
-
 #define INIT_AIO_CONTEXT { .reply_fd   = -1, \
                           .next        = NULL }
 
-extern int submit_aio(struct aio_context *aio);
+extern int submit_aio(enum aio_type type, int fd, char *buf, int len,
+                     unsigned long long offset, int reply_fd,
+                      struct aio_context *aio);
 
 #endif
index 6f766e1faeccd1bd806ddeb09546002c7e898d31..2e58e304b8be6ce3dc867ba2418432735fc07058 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef __OS_H__
 #define __OS_H__
 
+#include "uml-config.h"
 #include "asm/types.h"
 #include "../os/include/file.h"
 
@@ -159,7 +160,11 @@ extern int can_do_skas(void);
 
 /* Make sure they are clear when running in TT mode. Required by
  * SEGV_MAYBE_FIXABLE */
+#ifdef UML_CONFIG_MODE_SKAS
 #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
+#else
+#define clear_can_do_skas() do {} while (0)
+#endif
 
 /* mem.c */
 extern int create_mem_file(unsigned long len);
index f6e64026f9952b90d1af98625b152ef394c454e9..41cfb09442013325f7511949f8d6171e2bbac487 100644 (file)
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <signal.h>
-#include <string.h>
 #include <errno.h>
 #include <sched.h>
 #include <sys/syscall.h>
 #include "user.h"
 #include "mode.h"
 
+struct aio_thread_req {
+        enum aio_type type;
+        int io_fd;
+        unsigned long long offset;
+        char *buf;
+        int len;
+        struct aio_context *aio;
+};
+
 static int aio_req_fd_r = -1;
 static int aio_req_fd_w = -1;
 
-static int update_aio(struct aio_context *aio, int res)
-{
-        if(res < 0)
-                aio->len = res;
-        else if((res == 0) && (aio->type == AIO_READ)){
-                /* This is the EOF case - we have hit the end of the file
-                 * and it ends in a partial block, so we fill the end of
-                 * the block with zeros and claim success.
-                 */
-                memset(aio->data, 0, aio->len);
-                aio->len = 0;
-        }
-        else if(res > 0){
-                aio->len -= res;
-                aio->data += res;
-                aio->offset += res;
-                return aio->len;
-        }
-
-        return 0;
-}
-
 #if defined(HAVE_AIO_ABI)
 #include <linux/aio_abi.h>
 
@@ -80,7 +66,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
  * that it now backs the mmapped area.
  */
 
-static int do_aio(aio_context_t ctx, struct aio_context *aio)
+static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
+                  int len, unsigned long long offset, struct aio_context *aio)
 {
         struct iocb iocb, *iocbp = &iocb;
         char c;
@@ -88,39 +75,40 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio)
 
         iocb = ((struct iocb) { .aio_data      = (unsigned long) aio,
                                 .aio_reqprio   = 0,
-                                .aio_fildes    = aio->fd,
-                                .aio_buf       = (unsigned long) aio->data,
-                                .aio_nbytes    = aio->len,
-                                .aio_offset    = aio->offset,
+                                .aio_fildes    = fd,
+                                .aio_buf       = (unsigned long) buf,
+                                .aio_nbytes    = len,
+                                .aio_offset    = offset,
                                 .aio_reserved1 = 0,
                                 .aio_reserved2 = 0,
                                 .aio_reserved3 = 0 });
 
-        switch(aio->type){
+        switch(type){
         case AIO_READ:
                 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
+                err = io_submit(ctx, 1, &iocbp);
                 break;
         case AIO_WRITE:
                 iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
+                err = io_submit(ctx, 1, &iocbp);
                 break;
         case AIO_MMAP:
                 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
                 iocb.aio_buf = (unsigned long) &c;
                 iocb.aio_nbytes = sizeof(c);
+                err = io_submit(ctx, 1, &iocbp);
                 break;
         default:
-                printk("Bogus op in do_aio - %d\n", aio->type);
+                printk("Bogus op in do_aio - %d\n", type);
                 err = -EINVAL;
-                goto out;
+                break;
         }
 
-        err = io_submit(ctx, 1, &iocbp);
         if(err > 0)
                 err = 0;
        else
                err = -errno;
 
- out:
         return err;
 }
 
@@ -129,9 +117,8 @@ static aio_context_t ctx = 0;
 static int aio_thread(void *arg)
 {
         struct aio_thread_reply reply;
-        struct aio_context *aio;
         struct io_event event;
-        int err, n;
+        int err, n, reply_fd;
 
         signal(SIGWINCH, SIG_IGN);
 
@@ -144,22 +131,14 @@ static int aio_thread(void *arg)
                                "errno = %d\n", errno);
                 }
                 else {
-                       /* This is safe as we've just a pointer here. */
-                       aio = (struct aio_context *) (long) event.data;
-                       if(update_aio(aio, event.res)){
-                               do_aio(ctx, aio);
-                               continue;
-                       }
-
                         reply = ((struct aio_thread_reply)
-                               { .data = aio,
-                                 .err  = aio->len });
-                       err = os_write_file(aio->reply_fd, &reply,
-                                           sizeof(reply));
+                                { .data = (void *) (long) event.data,
+                                  .err = event.res });
+                       reply_fd = ((struct aio_context *) reply.data)->reply_fd;
+                       err = os_write_file(reply_fd, &reply, sizeof(reply));
                         if(err != sizeof(reply))
-                               printk("aio_thread - write failed, "
-                                      "fd = %d, err = %d\n", aio->reply_fd,
-                                      -err);
+                               printk("aio_thread - write failed, fd = %d, "
+                                       "err = %d\n", aio_req_fd_r, -err);
                 }
         }
         return 0;
@@ -167,35 +146,35 @@ static int aio_thread(void *arg)
 
 #endif
 
-static int do_not_aio(struct aio_context *aio)
+static int do_not_aio(struct aio_thread_req *req)
 {
         char c;
         int err;
 
-        switch(aio->type){
+        switch(req->type){
         case AIO_READ:
-                err = os_seek_file(aio->fd, aio->offset);
+                err = os_seek_file(req->io_fd, req->offset);
                 if(err)
                         goto out;
 
-                err = os_read_file(aio->fd, aio->data, aio->len);
+                err = os_read_file(req->io_fd, req->buf, req->len);
                 break;
         case AIO_WRITE:
-                err = os_seek_file(aio->fd, aio->offset);
+                err = os_seek_file(req->io_fd, req->offset);
                 if(err)
                         goto out;
 
-                err = os_write_file(aio->fd, aio->data, aio->len);
+                err = os_write_file(req->io_fd, req->buf, req->len);
                 break;
         case AIO_MMAP:
-                err = os_seek_file(aio->fd, aio->offset);
+                err = os_seek_file(req->io_fd, req->offset);
                 if(err)
                         goto out;
 
-                err = os_read_file(aio->fd, &c, sizeof(c));
+                err = os_read_file(req->io_fd, &c, sizeof(c));
                 break;
         default:
-                printk("do_not_aio - bad request type : %d\n", aio->type);
+                printk("do_not_aio - bad request type : %d\n", req->type);
                 err = -EINVAL;
                 break;
         }
@@ -206,14 +185,14 @@ static int do_not_aio(struct aio_context *aio)
 
 static int not_aio_thread(void *arg)
 {
-        struct aio_context *aio;
+        struct aio_thread_req req;
         struct aio_thread_reply reply;
         int err;
 
         signal(SIGWINCH, SIG_IGN);
         while(1){
-                err = os_read_file(aio_req_fd_r, &aio, sizeof(aio));
-                if(err != sizeof(aio)){
+                err = os_read_file(aio_req_fd_r, &req, sizeof(req));
+                if(err != sizeof(req)){
                         if(err < 0)
                                 printk("not_aio_thread - read failed, "
                                        "fd = %d, err = %d\n", aio_req_fd_r,
@@ -224,34 +203,17 @@ static int not_aio_thread(void *arg)
                         }
                         continue;
                 }
- again:
-                err = do_not_aio(aio);
-
-                if(update_aio(aio, err))
-                        goto again;
-
-                reply = ((struct aio_thread_reply) { .data     = aio,
-                                                     .err      = aio->len });
-                err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
+                err = do_not_aio(&req);
+                reply = ((struct aio_thread_reply) { .data     = req.aio,
+                                                     .err      = err });
+                err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
                 if(err != sizeof(reply))
                         printk("not_aio_thread - write failed, fd = %d, "
                                "err = %d\n", aio_req_fd_r, -err);
         }
 }
 
-static int submit_aio_24(struct aio_context *aio)
-{
-        int err;
-
-        err = os_write_file(aio_req_fd_w, &aio, sizeof(aio));
-        if(err == sizeof(aio))
-                err = 0;
-
-        return err;
-}
-
 static int aio_pid = -1;
-static int (*submit_proc)(struct aio_context *aio);
 
 static int init_aio_24(void)
 {
@@ -283,33 +245,11 @@ static int init_aio_24(void)
 #endif
        printk("2.6 host AIO support not used - falling back to I/O "
               "thread\n");
-
-       submit_proc = submit_aio_24;
-
         return 0;
 }
 
 #ifdef HAVE_AIO_ABI
 #define DEFAULT_24_AIO 0
-static int submit_aio_26(struct aio_context *aio)
-{
-       struct aio_thread_reply reply;
-       int err;
-
-       err = do_aio(ctx, aio);
-       if(err){
-               reply = ((struct aio_thread_reply) { .data = aio,
-                                                    .err  = err });
-               err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
-               if(err != sizeof(reply))
-                       printk("submit_aio_26 - write failed, "
-                              "fd = %d, err = %d\n", aio->reply_fd, -err);
-               else err = 0;
-       }
-
-       return err;
-}
-
 static int init_aio_26(void)
 {
         unsigned long stack;
@@ -330,22 +270,39 @@ static int init_aio_26(void)
         aio_pid = err;
 
        printk("Using 2.6 host AIO\n");
+        return 0;
+}
+
+static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
+                        unsigned long long offset, struct aio_context *aio)
+{
+        struct aio_thread_reply reply;
+        int err;
 
-       submit_proc = submit_aio_26;
+        err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
+        if(err){
+                reply = ((struct aio_thread_reply) { .data = aio,
+                                                     .err  = err });
+                err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
+                if(err != sizeof(reply))
+                        printk("submit_aio_26 - write failed, "
+                               "fd = %d, err = %d\n", aio->reply_fd, -err);
+                else err = 0;
+        }
 
-        return 0;
+        return err;
 }
 
 #else
 #define DEFAULT_24_AIO 1
-static int submit_aio_26(struct aio_context *aio)
+static int init_aio_26(void)
 {
         return -ENOSYS;
 }
 
-static int init_aio_26(void)
+static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
+                        unsigned long long offset, struct aio_context *aio)
 {
-       submit_proc = submit_aio_26;
         return -ENOSYS;
 }
 #endif
@@ -412,7 +369,33 @@ static void exit_aio(void)
 
 __uml_exitcall(exit_aio);
 
-int submit_aio(struct aio_context *aio)
+static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
+                        unsigned long long offset, struct aio_context *aio)
 {
-       return (*submit_proc)(aio);
+        struct aio_thread_req req = { .type            = type,
+                                      .io_fd           = io_fd,
+                                      .offset          = offset,
+                                      .buf             = buf,
+                                      .len             = len,
+                                      .aio             = aio,
+        };
+        int err;
+
+        err = os_write_file(aio_req_fd_w, &req, sizeof(req));
+        if(err == sizeof(req))
+                err = 0;
+
+        return err;
+}
+
+int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
+               unsigned long long offset, int reply_fd,
+               struct aio_context *aio)
+{
+        aio->reply_fd = reply_fd;
+        if(aio_24)
+                return submit_aio_24(type, io_fd, buf, len, offset, aio);
+        else {
+                return submit_aio_26(type, io_fd, buf, len, offset, aio);
+        }
 }
index fbf1c06ec5c12aac8c83defb67221339325337e3..40887f09b681ac8253e9faaa54c2c41aadb5c480 100644 (file)
@@ -903,8 +903,8 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
 
 static void e100_get_defaults(struct nic *nic)
 {
-       struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
-       struct param_range cbs  = { .min = 64, .max = 256, .count = 128 };
+       struct param_range rfds = { .min = 16, .max = 256, .count = 64 };
+       struct param_range cbs  = { .min = 64, .max = 256, .count = 64 };
 
        pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
        /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
@@ -1007,213 +1007,25 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
                c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
 }
 
-/********************************************************/
-/*  Micro code for 8086:1229 Rev 8                      */
-/********************************************************/
-
-/*  Parameter values for the D101M B-step  */
-#define D101M_CPUSAVER_TIMER_DWORD             78
-#define D101M_CPUSAVER_BUNDLE_DWORD            65
-#define D101M_CPUSAVER_MIN_SIZE_DWORD          126
-
-#define D101M_B_RCVBUNDLE_UCODE \
-{\
-0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
-0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
-0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
-0x00380438, 0x00000000, 0x00140000, 0x00380555, \
-0x00308000, 0x00100662, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
-0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
-0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
-0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
-0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
-0x00041000, 0x00010004, 0x00130826, 0x000C0006, \
-0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380C34, 0x00000000, 0x00000000, \
-0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
-0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
-0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
-0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
-0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
-0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
-0x00130826, 0x000C0001, 0x00220559, 0x00101313, \
-0x00380559, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00130831, 0x0010090B, 0x00124813, \
-0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
-0x003806A8, 0x00000000, 0x00000000, 0x00000000, \
-}
-
-/********************************************************/
-/*  Micro code for 8086:1229 Rev 9                      */
-/********************************************************/
-
-/*  Parameter values for the D101S  */
-#define D101S_CPUSAVER_TIMER_DWORD             78
-#define D101S_CPUSAVER_BUNDLE_DWORD            67
-#define D101S_CPUSAVER_MIN_SIZE_DWORD          128
-
-#define D101S_RCVBUNDLE_UCODE \
-{\
-0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
-0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
-0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
-0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
-0x00308000, 0x00100610, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
-0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
-0x003A047E, 0x00044010, 0x00380819, 0x00000000, \
-0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
-0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
-0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
-0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
-0x00101313, 0x00380700, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
-0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
-0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
-0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
-0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
-0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
-0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
-0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
-0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00130831, \
-0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
-0x00041000, 0x00010004, 0x00380700  \
-}
-
-/********************************************************/
-/*  Micro code for the 8086:1229 Rev F/10               */
-/********************************************************/
-
-/*  Parameter values for the D102 E-step  */
-#define D102_E_CPUSAVER_TIMER_DWORD            42
-#define D102_E_CPUSAVER_BUNDLE_DWORD           54
-#define D102_E_CPUSAVER_MIN_SIZE_DWORD         46
-
-#define     D102_E_RCVBUNDLE_UCODE \
-{\
-0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \
-0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
-0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
-0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
-0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
-0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \
-0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-}
-
 static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 {
-/* *INDENT-OFF* */
-       static struct {
-               u32 ucode[UCODE_SIZE + 1];
-               u8 mac;
-               u8 timer_dword;
-               u8 bundle_dword;
-               u8 min_size_dword;
-       } ucode_opts[] = {
-               { D101M_B_RCVBUNDLE_UCODE,
-                 mac_82559_D101M,
-                 D101M_CPUSAVER_TIMER_DWORD,
-                 D101M_CPUSAVER_BUNDLE_DWORD,
-                 D101M_CPUSAVER_MIN_SIZE_DWORD },
-               { D101S_RCVBUNDLE_UCODE,
-                 mac_82559_D101S,
-                 D101S_CPUSAVER_TIMER_DWORD,
-                 D101S_CPUSAVER_BUNDLE_DWORD,
-                 D101S_CPUSAVER_MIN_SIZE_DWORD },
-               { D102_E_RCVBUNDLE_UCODE,
-                 mac_82551_F,
-                 D102_E_CPUSAVER_TIMER_DWORD,
-                 D102_E_CPUSAVER_BUNDLE_DWORD,
-                 D102_E_CPUSAVER_MIN_SIZE_DWORD },
-               { D102_E_RCVBUNDLE_UCODE,
-                 mac_82551_10,
-                 D102_E_CPUSAVER_TIMER_DWORD,
-                 D102_E_CPUSAVER_BUNDLE_DWORD,
-                 D102_E_CPUSAVER_MIN_SIZE_DWORD },
-               { {0}, 0, 0, 0, 0}
-       }, *opts;
-/* *INDENT-ON* */
-
-#define BUNDLESMALL 1
-#define BUNDLEMAX 50
-#define INTDELAY 15000
-
-       opts = ucode_opts;
-
-       /* do not load u-code for ICH devices */
-       if (nic->flags & ich)
-               return;
-
-       /* Search for ucode match against h/w rev_id */
-       while (opts->mac) {
-               if (nic->mac == opts->mac) {
-                       int i;
-                       u32 *ucode = opts->ucode;
-
-                       /* Insert user-tunable settings */
-                       ucode[opts->timer_dword] &= 0xFFFF0000;
-                       ucode[opts->timer_dword] |=
-                               (u16) INTDELAY;
-                       ucode[opts->bundle_dword] &= 0xFFFF0000;
-                       ucode[opts->bundle_dword] |= (u16) BUNDLEMAX;
-                       ucode[opts->min_size_dword] &= 0xFFFF0000;
-                       ucode[opts->min_size_dword] |=
-                               (BUNDLESMALL) ?  0xFFFF : 0xFF80;
-
-                       for(i = 0; i < UCODE_SIZE; i++)
-                               cb->u.ucode[i] = cpu_to_le32(ucode[i]);
-                       cb->command = cpu_to_le16(cb_ucode);
-                       return;
-               }
-               opts++;
-       }
+       int i;
+       static const u32 ucode[UCODE_SIZE] = {
+               /* NFS packets are misinterpreted as TCO packets and
+                * incorrectly routed to the BMC over SMBus.  This
+                * microcode patch checks the fragmented IP bit in the
+                * NFS/UDP header to distinguish between NFS and TCO. */
+               0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF,
+               0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000,
+               0x00906EFD, 0x00900EFD, 0x00E00EF8,
+       };
 
-       cb->command = cpu_to_le16(cb_nop);
+       if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
+               for(i = 0; i < UCODE_SIZE; i++)
+                       cb->u.ucode[i] = cpu_to_le32(ucode[i]);
+               cb->command = cpu_to_le16(cb_ucode);
+       } else
+               cb->command = cpu_to_le16(cb_nop);
 }
 
 static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
index c05653c7779dd792855a138a8e4479911d08c592..cb832b03ec5e0cc0765523d571b8f8702eaa22c0 100644 (file)
@@ -29,6 +29,8 @@
  *  NV-specific details such as register offsets, SATA phy location,
  *  hotplug info, etc.
  *
+ *  0.09
+ *     - Fixed bug introduced by 0.08's MCP51 and MCP55 support.
  *
  *  0.08
  *     - Added support for MCP51 and MCP55.
@@ -132,9 +134,7 @@ enum nv_host_type
        GENERIC,
        NFORCE2,
        NFORCE3,
-       CK804,
-       MCP51,
-       MCP55
+       CK804
 };
 
 static struct pci_device_id nv_pci_tbl[] = {
@@ -153,13 +153,13 @@ static struct pci_device_id nv_pci_tbl[] = {
        { 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_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 },
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
                PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
index 53e0323d4b83c3ce49ce549f8bb6f4a7ecfb04d8..bdb4e454b8b07311a8a76597f768572f38afa476 100644 (file)
@@ -73,7 +73,7 @@ struct imx_port {
        struct uart_port        port;
        struct timer_list       timer;
        unsigned int            old_status;
-       int txirq,rxirq;
+       int txirq,rxirq,rtsirq;
 };
 
 /*
@@ -181,6 +181,22 @@ static void imx_start_tx(struct uart_port *port)
                imx_transmit_buffer(sport);
 }
 
+static irqreturn_t imx_rtsint(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct imx_port *sport = (struct imx_port *)dev_id;
+       unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+
+       USR1((u32)sport->port.membase) = USR1_RTSD;
+       uart_handle_cts_change(&sport->port, !!val);
+       wake_up_interruptible(&sport->port.info->delta_msr_wait);
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct imx_port *sport = (struct imx_port *)dev_id;
@@ -386,15 +402,21 @@ static int imx_startup(struct uart_port *port)
        if (retval) goto error_out1;
 
        retval = request_irq(sport->txirq, imx_txint, 0,
-                            "imx-uart", sport);
+                            DRIVER_NAME, sport);
        if (retval) goto error_out2;
 
+       retval = request_irq(sport->rtsirq, imx_rtsint, 0,
+                            DRIVER_NAME, sport);
+       if (retval) goto error_out3;
+       set_irq_type(sport->rtsirq, IRQT_BOTHEDGE);
+
        /*
         * Finally, clear and enable interrupts
         */
 
+       USR1((u32)sport->port.membase) = USR1_RTSD;
        UCR1((u32)sport->port.membase) |=
-                        (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
+                        (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
 
        UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN);
        /*
@@ -406,6 +428,8 @@ static int imx_startup(struct uart_port *port)
 
        return 0;
 
+error_out3:
+       free_irq(sport->txirq, sport);
 error_out2:
        free_irq(sport->rxirq, sport);
 error_out1:
@@ -424,6 +448,7 @@ static void imx_shutdown(struct uart_port *port)
        /*
         * Free the interrupts
         */
+       free_irq(sport->rtsirq, sport);
        free_irq(sport->txirq, sport);
        free_irq(sport->rxirq, sport);
 
@@ -432,7 +457,7 @@ static void imx_shutdown(struct uart_port *port)
         */
 
        UCR1((u32)sport->port.membase) &=
-                        ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
+                        ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
 }
 
 static void
@@ -522,7 +547,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
         * disable interrupts and drain transmitter
         */
        old_ucr1 = UCR1((u32)sport->port.membase);
-       UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
+       UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
 
        while ( !(USR2((u32)sport->port.membase) & USR2_TXDC))
                barrier();
@@ -643,6 +668,7 @@ static struct imx_port imx_ports[] = {
        {
        .txirq  = UART1_MINT_TX,
        .rxirq  = UART1_MINT_RX,
+       .rtsirq = UART1_MINT_RTS,
        .port   = {
                .type           = PORT_IMX,
                .iotype         = SERIAL_IO_MEM,
@@ -658,6 +684,7 @@ static struct imx_port imx_ports[] = {
        }, {
        .txirq  = UART2_MINT_TX,
        .rxirq  = UART2_MINT_RX,
+       .rtsirq = UART2_MINT_RTS,
        .port   = {
                .type           = PORT_IMX,
                .iotype         = SERIAL_IO_MEM,
@@ -737,7 +764,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 
        UCR1((u32)sport->port.membase) =
                           (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN)
-                          & ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
+                          & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
        UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
 
        /*
index 672b359b07ce4f48fd16b3e2e9fc0ecffdd59e3c..90c2a86c421b0cb3f8cb22eed95a120671d982d9 100644 (file)
@@ -499,7 +499,7 @@ serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
        /*
         * Update the per-port timeout.
         */
-       uart_update_timeout(port, termios->c_cflag, quot);
+       uart_update_timeout(port, termios->c_cflag, baud);
 
        up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
        if (termios->c_iflag & INPCK)
index eff2158024c8593feec0285b196e9ad1ab33dc54..52692aa345ecfec1fecff5a3aba6ccc820384c80 100644 (file)
@@ -1092,8 +1092,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 
 static int probe_index = 0;
 
-int s3c24xx_serial_probe(struct device *_dev,
-                        struct s3c24xx_uart_info *info)
+static int s3c24xx_serial_probe(struct device *_dev,
+                               struct s3c24xx_uart_info *info)
 {
        struct s3c24xx_uart_port *ourport;
        struct platform_device *dev = to_platform_device(_dev);
@@ -1120,7 +1120,7 @@ int s3c24xx_serial_probe(struct device *_dev,
        return ret;
 }
 
-int s3c24xx_serial_remove(struct device *_dev)
+static int s3c24xx_serial_remove(struct device *_dev)
 {
        struct uart_port *port = s3c24xx_dev_to_port(_dev);
 
@@ -1134,7 +1134,8 @@ int s3c24xx_serial_remove(struct device *_dev)
 
 #ifdef CONFIG_PM
 
-int s3c24xx_serial_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c24xx_serial_suspend(struct device *dev, pm_message_t state,
+                                 u32 level)
 {
        struct uart_port *port = s3c24xx_dev_to_port(dev);
 
@@ -1144,7 +1145,7 @@ int s3c24xx_serial_suspend(struct device *dev, pm_message_t state, u32 level)
        return 0;
 }
 
-int s3c24xx_serial_resume(struct device *dev, u32 level)
+static int s3c24xx_serial_resume(struct device *dev, u32 level)
 {
        struct uart_port *port = s3c24xx_dev_to_port(dev);
        struct s3c24xx_uart_port *ourport = to_ourport(port);
@@ -1165,8 +1166,8 @@ int s3c24xx_serial_resume(struct device *dev, u32 level)
 #define s3c24xx_serial_resume  NULL
 #endif
 
-int s3c24xx_serial_init(struct device_driver *drv,
-                       struct s3c24xx_uart_info *info)
+static int s3c24xx_serial_init(struct device_driver *drv,
+                              struct s3c24xx_uart_info *info)
 {
        dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
        return driver_register(drv);
index e971156daa60c49e94fcf26ae1ddc3a3b3e387ad..ba9381fd3f2da3916e309cc41ad535a448d566ac 100644 (file)
@@ -274,7 +274,6 @@ static void transmit_chars(struct uart_sunsab_port *up,
        if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
                up->interrupt_mask1 |= SAB82532_IMR1_XPR;
                writeb(up->interrupt_mask1, &up->regs->w.imr1);
-               uart_write_wakeup(&up->port);
                return;
        }
 
index d75445738c881d4ef442455e5b0b9e3a335be5bd..7653d6cf05aff66a697e3c057682cfafeab0b177 100644 (file)
@@ -517,10 +517,9 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
        if (up->port.info == NULL)
                goto ack_tx_int;
        xmit = &up->port.info->xmit;
-       if (uart_circ_empty(xmit)) {
-               uart_write_wakeup(&up->port);
+       if (uart_circ_empty(xmit))
                goto ack_tx_int;
-       }
+
        if (uart_tx_stopped(&up->port))
                goto ack_tx_int;
 
index 939d9e5020a0915f5c7ac7e5a50c49533187904f..13fa2deb4dddfca1dc5237558cf14d359ab67c3a 100644 (file)
 #define DRCMR12                __REG(0x40000130)  /* Request to Channel Map Register for AC97 audio transmit Request */
 #define DRCMR13                __REG(0x40000134)  /* Request to Channel Map Register for SSP receive Request */
 #define DRCMR14                __REG(0x40000138)  /* Request to Channel Map Register for SSP transmit Request */
-#define DRCMR15                __REG(0x4000013c)  /* Reserved */
-#define DRCMR16                __REG(0x40000140)  /* Reserved */
+#define DRCMR15                __REG(0x4000013c)  /* Request to Channel Map Register for SSP2 receive Request */
+#define DRCMR16                __REG(0x40000140)  /* Request to Channel Map Register for SSP2 transmit Request */
 #define DRCMR17                __REG(0x40000144)  /* Request to Channel Map Register for ICP receive Request */
 #define DRCMR18                __REG(0x40000148)  /* Request to Channel Map Register for ICP transmit Request */
 #define DRCMR19                __REG(0x4000014c)  /* Request to Channel Map Register for STUART receive Request */
 #define DRCMR37                __REG(0x40000194)  /* Request to Channel Map Register for USB endpoint 13 Request */
 #define DRCMR38                __REG(0x40000198)  /* Request to Channel Map Register for USB endpoint 14 Request */
 #define DRCMR39                __REG(0x4000019C)  /* Reserved */
-
+#define DRCMR66                __REG(0x40001108)  /* Request to Channel Map Register for SSP3 receive Request */
+#define DRCMR67                __REG(0x4000110C)  /* Request to Channel Map Register for SSP3 transmit Request */
 #define DRCMR68                __REG(0x40001110)  /* Request to Channel Map Register for Camera FIFO 0 Request */
 #define DRCMR69                __REG(0x40001114)  /* Request to Channel Map Register for Camera FIFO 1 Request */
 #define DRCMR70                __REG(0x40001118)  /* Request to Channel Map Register for Camera FIFO 2 Request */
index 48a39918a76094a579cf8e7465e997715ddbaafe..1c9de29cafef1b7684a1e5ea4b7a0236f7166fb1 100644 (file)
@@ -92,6 +92,13 @@ extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
 
 extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg);
 
+#ifdef CONFIG_CPU_S3C2440
+
+extern int s3c2440_set_dsc(unsigned int pin, unsigned int value);
+
+#endif /* CONFIG_CPU_S3C2440 */
+
+
 #endif /* __ASSEMBLY__ */
 
 #include <asm/sizes.h>
index 51c5b316be55e7ae7125e3c6587ea258414d0666..c02d15aced9106b3d3a85517837759ccb883e80b 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/config.h>
 #include <asm/cputable.h>
 
-#define CLOCK_TICK_RATE        1193180 /* Underlying HZ */
+#define CLOCK_TICK_RATE        1024000 /* Underlying HZ */
 
 typedef unsigned long cycles_t;
 
index 41d8f8425c04e3312ab2f8eada4307f191810bc1..e17c492c870bb6f4b52293c6e941abde4cacb4bd 100644 (file)
@@ -24,6 +24,7 @@
 #define PPC_FEATURE_HAS_SPE            0x00800000
 #define PPC_FEATURE_HAS_EFP_SINGLE     0x00400000
 #define PPC_FEATURE_HAS_EFP_DOUBLE     0x00200000
+#define PPC_FEATURE_NO_TB              0x00100000
 
 #ifdef __KERNEL__
 
index b15826f6e3a277b965cfb5fcf792fa13ef9e53f4..fe9778301d07b44ef705c530d7f28b82f6688ffa 100644 (file)
@@ -392,4 +392,16 @@ extern cpumask_t cpu_present_map;
 #define for_each_online_cpu(cpu)  for_each_cpu_mask((cpu), cpu_online_map)
 #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map)
 
+/* Find the highest possible smp_processor_id() */
+static inline unsigned int highest_possible_processor_id(void)
+{
+       unsigned int cpu, highest = 0;
+
+       for_each_cpu_mask(cpu, cpu_possible_map)
+               highest = cpu;
+
+       return highest;
+}
+
+
 #endif /* __LINUX_CPUMASK_H */
index 1d5b10ae2399f62f6573167d5c17b0c5e9267ea3..f08e870100f4916b2553c07365e732407c77360c 100644 (file)
@@ -41,11 +41,15 @@ enum nfnetlink_groups {
 struct nfattr
 {
        u_int16_t nfa_len;
-       u_int16_t nfa_type;
+       u_int16_t nfa_type;     /* we use 15 bits for the type, and the highest
+                                * bit to indicate whether the payload is nested */
 } __attribute__ ((packed));
 
-/* FIXME: Shamelessly copy and pasted from rtnetlink.h, it's time
- *       to put this in a generic file */
+/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from
+ * rtnetlink.h, it's time to put this in a generic file */
+
+#define NFNL_NFA_NEST  0x8000
+#define NFA_TYPE(attr)         ((attr)->nfa_type & 0x7fff)
 
 #define NFA_ALIGNTO     4
 #define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
@@ -59,7 +63,7 @@ struct nfattr
 #define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
 #define NFA_NEST(skb, type) \
 ({     struct nfattr *__start = (struct nfattr *) (skb)->tail; \
-       NFA_PUT(skb, type, 0, NULL); \
+       NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \
        __start;  })
 #define NFA_NEST_END(skb, start) \
 ({      (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \
index 5c55751c78e4d3a83cc2b29a7d4e20bfdaeeaaa8..116fcaced909f3ed78c87688c2065ce23640bcd8 100644 (file)
@@ -70,15 +70,24 @@ enum ctattr_l4proto {
 
 enum ctattr_protoinfo {
        CTA_PROTOINFO_UNSPEC,
-       CTA_PROTOINFO_TCP_STATE,
+       CTA_PROTOINFO_TCP,
        __CTA_PROTOINFO_MAX
 };
 #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
 
+enum ctattr_protoinfo_tcp {
+       CTA_PROTOINFO_TCP_UNSPEC,
+       CTA_PROTOINFO_TCP_STATE,
+       __CTA_PROTOINFO_TCP_MAX
+};
+#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
+
 enum ctattr_counters {
        CTA_COUNTERS_UNSPEC,
-       CTA_COUNTERS_PACKETS,
-       CTA_COUNTERS_BYTES,
+       CTA_COUNTERS_PACKETS,           /* old 64bit counters */
+       CTA_COUNTERS_BYTES,             /* old 64bit counters */
+       CTA_COUNTERS32_PACKETS,
+       CTA_COUNTERS32_BYTES,
        __CTA_COUNTERS_MAX
 };
 #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
index 4ced3873681313ad4d9ead8edd868000a6cc7dbd..d078bb91d9e5d4b6cf165b6689b5268a0eac7d2d 100644 (file)
@@ -117,6 +117,10 @@ enum ip_conntrack_events
        /* NAT info */
        IPCT_NATINFO_BIT = 10,
        IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
+
+       /* Counter highest bit has been set */
+       IPCT_COUNTER_FILLING_BIT = 11,
+       IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
 };
 
 enum ip_conntrack_expect_events {
@@ -192,8 +196,8 @@ do {                                                                        \
 
 struct ip_conntrack_counter
 {
-       u_int64_t packets;
-       u_int64_t bytes;
+       u_int32_t packets;
+       u_int32_t bytes;
 };
 
 struct ip_conntrack_helper;
index b6b99be8632a8709687e7b003858e1ee2f2de586..2c76b879e3dc1b774c364f244d5a910fa116d08d 100644 (file)
@@ -52,6 +52,9 @@ struct ip_conntrack_protocol
        int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
                         const struct ip_conntrack *ct);
 
+       /* convert nfnetlink attributes to protoinfo */
+       int (*from_nfattr)(struct nfattr *tb[], struct ip_conntrack *ct);
+
        int (*tuple_to_nfattr)(struct sk_buff *skb,
                               const struct ip_conntrack_tuple *t);
        int (*nfattr_to_tuple)(struct nfattr *tb[],
index 20e43f018b7c768cc8b9c13c23253e99c5561d6c..3232db11a4e54b6894ac35cbe669d1182629e252 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _IP_CONNTRACK_TUPLE_H
 #define _IP_CONNTRACK_TUPLE_H
 
+#include <linux/types.h>
+
 /* A `tuple' is a structure containing the information to uniquely
   identify a connection.  ie. if two packets have the same tuple, they
   are in the same connection; if not, they are not.
index e201ec6e990550004d03cb60c10ad07b96892882..41a107de17cf547510a4923b58595df400a45472 100644 (file)
@@ -58,10 +58,6 @@ extern rwlock_t ip_nat_lock;
 struct ip_nat_info
 {
        struct list_head bysource;
-
-       /* Helper (NULL if none). */
-       struct ip_nat_helper *helper;
-
        struct ip_nat_seq seq[IP_CT_DIR_MAX];
 };
 
index 5ade54a78dbbb3a3618d10d5e3d21d5d67a5b2fe..ca5a8733000fa08b65c21b3456b052b9f48dde21 100644 (file)
@@ -86,7 +86,7 @@ static inline void netpoll_poll_unlock(void *have)
 
 #else
 #define netpoll_rx(a) 0
-#define netpoll_poll_lock(a) 0
+#define netpoll_poll_lock(a) NULL
 #define netpoll_poll_unlock(a)
 #endif
 
index 4ade56ef3a4da8894a42978a7663d883219cc3df..28f7b2103505edc6cd4389e96aeca02845b1192d 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/ip.h>
 #include <linux/list.h>
+#include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
@@ -193,11 +194,13 @@ static inline u32 inet_rcv_saddr(const struct sock *sk)
 static inline void inet_twsk_put(struct inet_timewait_sock *tw)
 {
        if (atomic_dec_and_test(&tw->tw_refcnt)) {
+               struct module *owner = tw->tw_prot->owner;
 #ifdef SOCK_REFCNT_DEBUG
                printk(KERN_DEBUG "%s timewait_sock %p released\n",
                       tw->tw_prot->name, tw);
 #endif
                kmem_cache_free(tw->tw_prot->twsk_slab, tw);
+               module_put(owner);
        }
 }
 
index 91bb895375f4c8e90c4ef6190e19dd7de4de6c0f..defcf6a8607c3714f54dbb225b471570837dc630 100644 (file)
@@ -79,7 +79,6 @@ static void destroy_nbp(struct net_bridge_port *p)
 {
        struct net_device *dev = p->dev;
 
-       dev->br_port = NULL;
        p->br = NULL;
        p->dev = NULL;
        dev_put(dev);
@@ -100,6 +99,7 @@ static void del_nbp(struct net_bridge_port *p)
        struct net_bridge *br = p->br;
        struct net_device *dev = p->dev;
 
+       dev->br_port = NULL;
        dev_set_promiscuity(dev, -1);
 
        spin_lock_bh(&br->lock);
index c4540144f0f4384356a6ce72b6dd01bddcf7a83f..f8ffbf6e23336a7ec184b1358d388ff42c55b28c 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
 #include <linux/smp.h>
+#include <linux/cpumask.h>
 #include <net/sock.h>
 /* needed for logical [in,out]-dev filtering */
 #include "../br_private.h"
@@ -823,10 +824,11 @@ static int translate_table(struct ebt_replace *repl,
                /* this will get free'd in do_replace()/ebt_register_table()
                   if an error occurs */
                newinfo->chainstack = (struct ebt_chainstack **)
-                  vmalloc(num_possible_cpus() * sizeof(struct ebt_chainstack));
+                  vmalloc((highest_possible_processor_id()+1) 
+                                               * sizeof(struct ebt_chainstack));
                if (!newinfo->chainstack)
                        return -ENOMEM;
-               for (i = 0; i < num_possible_cpus(); i++) {
+               for_each_cpu(i) {
                        newinfo->chainstack[i] =
                           vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
                        if (!newinfo->chainstack[i]) {
@@ -895,9 +897,12 @@ static void get_counters(struct ebt_counter *oldcounters,
 
        /* counters of cpu 0 */
        memcpy(counters, oldcounters,
-          sizeof(struct ebt_counter) * nentries);
+              sizeof(struct ebt_counter) * nentries);
+
        /* add other counters to those of cpu 0 */
-       for (cpu = 1; cpu < num_possible_cpus(); cpu++) {
+       for_each_cpu(cpu) {
+               if (cpu == 0)
+                       continue;
                counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
                for (i = 0; i < nentries; i++) {
                        counters[i].pcnt += counter_base[i].pcnt;
@@ -929,7 +934,8 @@ static int do_replace(void __user *user, unsigned int len)
                BUGPRINT("Entries_size never zero\n");
                return -EINVAL;
        }
-       countersize = COUNTER_OFFSET(tmp.nentries) * num_possible_cpus();
+       countersize = COUNTER_OFFSET(tmp.nentries) * 
+                                       (highest_possible_processor_id()+1);
        newinfo = (struct ebt_table_info *)
           vmalloc(sizeof(struct ebt_table_info) + countersize);
        if (!newinfo)
@@ -1022,7 +1028,7 @@ static int do_replace(void __user *user, unsigned int len)
 
        vfree(table->entries);
        if (table->chainstack) {
-               for (i = 0; i < num_possible_cpus(); i++)
+               for_each_cpu(i)
                        vfree(table->chainstack[i]);
                vfree(table->chainstack);
        }
@@ -1040,7 +1046,7 @@ free_counterstmp:
        vfree(counterstmp);
        /* can be initialized in translate_table() */
        if (newinfo->chainstack) {
-               for (i = 0; i < num_possible_cpus(); i++)
+               for_each_cpu(i)
                        vfree(newinfo->chainstack[i]);
                vfree(newinfo->chainstack);
        }
@@ -1132,7 +1138,8 @@ int ebt_register_table(struct ebt_table *table)
                return -EINVAL;
        }
 
-       countersize = COUNTER_OFFSET(table->table->nentries) * num_possible_cpus();
+       countersize = COUNTER_OFFSET(table->table->nentries) *
+                                       (highest_possible_processor_id()+1);
        newinfo = (struct ebt_table_info *)
           vmalloc(sizeof(struct ebt_table_info) + countersize);
        ret = -ENOMEM;
@@ -1186,7 +1193,7 @@ free_unlock:
        up(&ebt_mutex);
 free_chainstack:
        if (newinfo->chainstack) {
-               for (i = 0; i < num_possible_cpus(); i++)
+               for_each_cpu(i)
                        vfree(newinfo->chainstack[i]);
                vfree(newinfo->chainstack);
        }
@@ -1209,7 +1216,7 @@ void ebt_unregister_table(struct ebt_table *table)
        up(&ebt_mutex);
        vfree(table->private->entries);
        if (table->private->chainstack) {
-               for (i = 0; i < num_possible_cpus(); i++)
+               for_each_cpu(i)
                        vfree(table->private->chainstack[i]);
                vfree(table->private->chainstack);
        }
index 21e55142dcd3b9b85e5c54d6630a788b3d74637c..c37eeeaf5c6e21982c341391d8d8db1a9929bdb9 100644 (file)
@@ -110,14 +110,14 @@ static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
 
 static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
 {
-       if (ccid->ccid_hc_rx_exit != NULL &&
+       if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL &&
            dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
                ccid->ccid_hc_rx_exit(sk);
 }
 
 static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
 {
-       if (ccid->ccid_hc_tx_exit != NULL &&
+       if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL &&
            dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL)
                ccid->ccid_hc_tx_exit(sk);
 }
index 1b6b2cb12376ecb27edadcd81eb32ff0a4716a1b..3454d59419006d7f83e4d3858cfecb3e93af773d 100644 (file)
@@ -375,6 +375,9 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
        case DCCP_PKT_RESET:
                inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
                break;
+       case DCCP_PKT_DATA:
+               if (sk->sk_state == DCCP_RESPOND)
+                       break;
        case DCCP_PKT_DATAACK:
        case DCCP_PKT_ACK:
                /*
@@ -393,7 +396,8 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
                dccp_sk(sk)->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq;
                dccp_set_state(sk, DCCP_OPEN);
 
-               if (dh->dccph_type == DCCP_PKT_DATAACK) {
+               if (dh->dccph_type == DCCP_PKT_DATAACK ||
+                   dh->dccph_type == DCCP_PKT_DATA) {
                        dccp_rcv_established(sk, skb, dh, len);
                        queued = 1; /* packet was queued
                                       (by dccp_rcv_established) */
index 1b5a09d1b90b77ca26b03210e974746f7b316218..1b18ce66e7b7ac1781c8c334c9f44d3dbac017a2 100644 (file)
@@ -5,6 +5,7 @@
 #include <net/esp.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
+#include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
 #include <net/icmp.h>
@@ -42,10 +43,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
        esp = x->data;
        alen = esp->auth.icv_trunc_len;
        tfm = esp->conf.tfm;
-       blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3;
-       clen = (clen + 2 + blksize-1)&~(blksize-1);
+       blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4);
+       clen = ALIGN(clen + 2, blksize);
        if (esp->conf.padlen)
-               clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+               clen = ALIGN(clen, esp->conf.padlen);
 
        if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0)
                goto error;
@@ -143,7 +144,7 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
        struct ip_esp_hdr *esph;
        struct esp_data *esp = x->data;
        struct sk_buff *trailer;
-       int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+       int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
        int alen = esp->auth.icv_trunc_len;
        int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
        int nfrags;
@@ -304,16 +305,16 @@ static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap,
 static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
 {
        struct esp_data *esp = x->data;
-       u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+       u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
 
        if (x->props.mode) {
-               mtu = (mtu + 2 + blksize-1)&~(blksize-1);
+               mtu = ALIGN(mtu + 2, blksize);
        } else {
                /* The worst case. */
-               mtu += 2 + blksize;
+               mtu = ALIGN(mtu + 2, 4) + blksize - 4;
        }
        if (esp->conf.padlen)
-               mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+               mtu = ALIGN(mtu, esp->conf.padlen);
 
        return mtu + x->props.header_len + esp->auth.icv_trunc_len;
 }
index f9076ef3a1a810b54ef5671d9620b5960cff8ac0..a010e9a68811cf325f75b6b894849cd2a58303cc 100644 (file)
@@ -111,6 +111,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
                tw->tw_prot         = sk->sk_prot_creator;
                atomic_set(&tw->tw_refcnt, 1);
                inet_twsk_dead_node_init(tw);
+               __module_get(tw->tw_prot->owner);
        }
 
        return tw;
index a7659728e7a0a86abea82923e841cc9bf733458c..7d917e4ce1d9761d15b9917f78f35b8ce9ec4797 100644 (file)
@@ -139,6 +139,7 @@ config IP_NF_AMANDA
 
 config IP_NF_PPTP
        tristate  'PPTP protocol support'
+       depends on IP_NF_CONNTRACK
        help
          This module adds support for PPTP (Point to Point Tunnelling
          Protocol, RFC2637) connection tracking and NAT. 
@@ -498,9 +499,14 @@ config IP_NF_TARGET_LOG
          To compile it as a module, choose M here.  If unsure, say N.
 
 config IP_NF_TARGET_ULOG
-       tristate "ULOG target support"
+       tristate "ULOG target support (OBSOLETE)"
        depends on IP_NF_IPTABLES
        ---help---
+
+         This option enables the old IPv4-only "ipt_ULOG" implementation
+         which has been obsoleted by the new "nfnetlink_log" code (see
+         CONFIG_NETFILTER_NETLINK_LOG).
+
          This option adds a `ULOG' target, which allows you to create rules in
          any iptables table. The packet is passed to a userspace logging
          daemon using netlink multicast sockets; unlike the LOG target
index fa1634256680d88f524727da2b48fdfe92360732..a7969286e6e721ecf371aaed4ca242c92eaa07b7 100644 (file)
@@ -716,8 +716,10 @@ static int translate_table(const char *name,
        }
 
        /* And one copy for every other CPU */
-       for (i = 1; i < num_possible_cpus(); i++) {
-               memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
+       for_each_cpu(i) {
+               if (i == 0)
+                       continue;
+               memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,
                       newinfo->entries,
                       SMP_ALIGN(newinfo->size));
        }
@@ -767,7 +769,7 @@ static void get_counters(const struct arpt_table_info *t,
        unsigned int cpu;
        unsigned int i;
 
-       for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
+       for_each_cpu(cpu) {
                i = 0;
                ARPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
                                   t->size,
@@ -885,7 +887,8 @@ static int do_replace(void __user *user, unsigned int len)
                return -ENOMEM;
 
        newinfo = vmalloc(sizeof(struct arpt_table_info)
-                         + SMP_ALIGN(tmp.size) * num_possible_cpus());
+                         + SMP_ALIGN(tmp.size) *
+                                       (highest_possible_processor_id()+1));
        if (!newinfo)
                return -ENOMEM;
 
@@ -1158,7 +1161,8 @@ int arpt_register_table(struct arpt_table *table,
                = { 0, 0, 0, { 0 }, { 0 }, { } };
 
        newinfo = vmalloc(sizeof(struct arpt_table_info)
-                         + SMP_ALIGN(repl->size) * num_possible_cpus());
+                         + SMP_ALIGN(repl->size) *
+                                       (highest_possible_processor_id()+1));
        if (!newinfo) {
                ret = -ENOMEM;
                return ret;
index ea65dd3e517abc20e5cf14034f7c7511f979827b..07a80b56e8dce24f421e98d4efb89589748bed3a 100644 (file)
@@ -1119,7 +1119,7 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
                        unsigned long extra_jiffies,
                        int do_acct)
 {
-       int do_event = 0;
+       int event = 0;
 
        IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
        IP_NF_ASSERT(skb);
@@ -1129,13 +1129,13 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
        /* If not in hash table, timer will not be active yet */
        if (!is_confirmed(ct)) {
                ct->timeout.expires = extra_jiffies;
-               do_event = 1;
+               event = IPCT_REFRESH;
        } else {
                /* Need del_timer for race avoidance (may already be dying). */
                if (del_timer(&ct->timeout)) {
                        ct->timeout.expires = jiffies + extra_jiffies;
                        add_timer(&ct->timeout);
-                       do_event = 1;
+                       event = IPCT_REFRESH;
                }
        }
 
@@ -1144,14 +1144,17 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
                ct->counters[CTINFO2DIR(ctinfo)].packets++;
                ct->counters[CTINFO2DIR(ctinfo)].bytes += 
                                                ntohs(skb->nh.iph->tot_len);
+               if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
+                   || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
+                       event |= IPCT_COUNTER_FILLING;
        }
 #endif
 
        write_unlock_bh(&ip_conntrack_lock);
 
        /* must be unlocked when calling event cache */
-       if (do_event)
-               ip_conntrack_event_cache(IPCT_REFRESH, skb);
+       if (event)
+               ip_conntrack_event_cache(event, skb);
 }
 
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
index b08a432efcf8e9d601005f5c31f666f815ccd2a0..166e6069f1212302c16c150fb267161af33ccc0d 100644 (file)
@@ -177,11 +177,11 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct,
        struct nfattr *nest_count = NFA_NEST(skb, type);
        u_int64_t tmp;
 
-       tmp = cpu_to_be64(ct->counters[dir].packets);
-       NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(u_int64_t), &tmp);
+       tmp = htonl(ct->counters[dir].packets);
+       NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
 
-       tmp = cpu_to_be64(ct->counters[dir].bytes);
-       NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(u_int64_t), &tmp);
+       tmp = htonl(ct->counters[dir].bytes);
+       NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
 
        NFA_NEST_END(skb, nest_count);
 
@@ -833,7 +833,8 @@ out:
 static inline int
 ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
 {
-       unsigned long d, status = *(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]);
+       unsigned long d;
+       unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
        d = ct->status ^ status;
 
        if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
@@ -948,6 +949,31 @@ ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[])
        return 0;
 }
 
+static inline int
+ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[])
+{
+       struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
+       struct ip_conntrack_protocol *proto;
+       u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
+       int err = 0;
+
+       if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0)
+               goto nfattr_failure;
+
+       proto = ip_conntrack_proto_find_get(npt);
+       if (!proto)
+               return -EINVAL;
+
+       if (proto->from_nfattr)
+               err = proto->from_nfattr(tb, ct);
+       ip_conntrack_proto_put(proto); 
+
+       return err;
+
+nfattr_failure:
+       return -ENOMEM;
+}
+
 static int
 ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
 {
@@ -973,6 +999,12 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
                        return err;
        }
 
+       if (cda[CTA_PROTOINFO-1]) {
+               err = ctnetlink_change_protoinfo(ct, cda);
+               if (err < 0)
+                       return err;
+       }
+
        DEBUGP("all done\n");
        return 0;
 }
@@ -1002,6 +1034,12 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
        if (err < 0)
                goto err;
 
+       if (cda[CTA_PROTOINFO-1]) {
+               err = ctnetlink_change_protoinfo(ct, cda);
+               if (err < 0)
+                       return err;
+       }
+
        ct->helper = ip_conntrack_helper_find_get(rtuple);
 
        add_timer(&ct->timeout);
index 838d1d69b36e0acd868038124c39a81d3a92722b..98f0015dd255ab593563fcc110b8c5ff67380183 100644 (file)
@@ -296,8 +296,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
                                struct ip_conntrack_tuple *tuple)
 {
        if (!tb[CTA_PROTO_ICMP_TYPE-1]
-           || !tb[CTA_PROTO_ICMP_CODE-1]
-           || !tb[CTA_PROTO_ICMP_ID-1])
+           || !tb[CTA_PROTO_ICMP_CODE-1])
                return -1;
 
        tuple->dst.u.icmp.type = 
index 121760d6cc50cd2ccd4568591168988606ab15d3..d6701cafbcc22311156a92e06fae3e29a02be8ac 100644 (file)
@@ -341,17 +341,43 @@ static int tcp_print_conntrack(struct seq_file *s,
 static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
                         const struct ip_conntrack *ct)
 {
+       struct nfattr *nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
+       
        read_lock_bh(&tcp_lock);
        NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
                &ct->proto.tcp.state);
        read_unlock_bh(&tcp_lock);
 
+       NFA_NEST_END(skb, nest_parms);
+
        return 0;
 
 nfattr_failure:
        read_unlock_bh(&tcp_lock);
        return -1;
 }
+
+static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct)
+{
+       struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
+       struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
+
+        if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0)
+                goto nfattr_failure;
+
+       if (!tb[CTA_PROTOINFO_TCP_STATE-1])
+               return -EINVAL;
+
+       write_lock_bh(&tcp_lock);
+       ct->proto.tcp.state = 
+               *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
+       write_unlock_bh(&tcp_lock);
+
+       return 0;
+
+nfattr_failure:
+       return -1;
+}
 #endif
 
 static unsigned int get_conntrack_index(const struct tcphdr *tcph)
@@ -1123,6 +1149,7 @@ struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
        .to_nfattr              = tcp_to_nfattr,
+       .from_nfattr            = nfattr_to_tcp,
        .tuple_to_nfattr        = ip_ct_port_tuple_to_nfattr,
        .nfattr_to_tuple        = ip_ct_port_nfattr_to_tuple,
 #endif
index eef99a1b5de6e5fd35103497e8caa13458f11820..75c27e92f6abb521ac8f42ff28a2040177470503 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/semaphore.h>
 #include <linux/proc_fs.h>
 #include <linux/err.h>
+#include <linux/cpumask.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 
@@ -921,8 +922,10 @@ translate_table(const char *name,
        }
 
        /* And one copy for every other CPU */
-       for (i = 1; i < num_possible_cpus(); i++) {
-               memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
+       for_each_cpu(i) {
+               if (i == 0)
+                       continue;
+               memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,
                       newinfo->entries,
                       SMP_ALIGN(newinfo->size));
        }
@@ -943,7 +946,7 @@ replace_table(struct ipt_table *table,
                struct ipt_entry *table_base;
                unsigned int i;
 
-               for (i = 0; i < num_possible_cpus(); i++) {
+               for_each_cpu(i) {
                        table_base =
                                (void *)newinfo->entries
                                + TABLE_OFFSET(newinfo, i);
@@ -990,7 +993,7 @@ get_counters(const struct ipt_table_info *t,
        unsigned int cpu;
        unsigned int i;
 
-       for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
+       for_each_cpu(cpu) {
                i = 0;
                IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
                                  t->size,
@@ -1128,7 +1131,8 @@ do_replace(void __user *user, unsigned int len)
                return -ENOMEM;
 
        newinfo = vmalloc(sizeof(struct ipt_table_info)
-                         + SMP_ALIGN(tmp.size) * num_possible_cpus());
+                         + SMP_ALIGN(tmp.size) * 
+                               (highest_possible_processor_id()+1));
        if (!newinfo)
                return -ENOMEM;
 
@@ -1458,7 +1462,8 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
                = { 0, 0, 0, { 0 }, { 0 }, { } };
 
        newinfo = vmalloc(sizeof(struct ipt_table_info)
-                         + SMP_ALIGN(repl->size) * num_possible_cpus());
+                         + SMP_ALIGN(repl->size) * 
+                                       (highest_possible_processor_id()+1));
        if (!newinfo)
                return -ENOMEM;
 
index 8225e4257258a13b5697c255290e5741dc642f0f..7114031fdc70e3ce8c6adcdd7beda2f6d2b5d049 100644 (file)
@@ -435,7 +435,16 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
        int nsize, old_factor;
        u16 flags;
 
-       BUG_ON(len >= skb->len);
+       if (unlikely(len >= skb->len)) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "TCP: seg_size=%u, mss=%u, seq=%u, "
+                              "end_seq=%u, skb->len=%u.\n", len, mss_now,
+                              TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
+                              skb->len);
+                       WARN_ON(1);
+               }
+               return 0;
+       }
 
        nsize = skb_headlen(skb) - len;
        if (nsize < 0)
index 9b27460f0cc703412e3fb71bba690553cdf799da..40d9a1935ab5e5911e2922499fd571afe0005741 100644 (file)
@@ -31,6 +31,7 @@
 #include <net/esp.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
+#include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
 #include <net/icmp.h>
@@ -66,10 +67,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 
        alen = esp->auth.icv_trunc_len;
        tfm = esp->conf.tfm;
-       blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3;
-       clen = (clen + 2 + blksize-1)&~(blksize-1);
+       blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4);
+       clen = ALIGN(clen + 2, blksize);
        if (esp->conf.padlen)
-               clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+               clen = ALIGN(clen, esp->conf.padlen);
 
        if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
                goto error;
@@ -133,7 +134,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru
        struct ipv6_esp_hdr *esph;
        struct esp_data *esp = x->data;
        struct sk_buff *trailer;
-       int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+       int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
        int alen = esp->auth.icv_trunc_len;
        int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
 
@@ -235,16 +236,17 @@ out_nofree:
 static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
 {
        struct esp_data *esp = x->data;
-       u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+       u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
 
        if (x->props.mode) {
-               mtu = (mtu + 2 + blksize-1)&~(blksize-1);
+               mtu = ALIGN(mtu + 2, blksize);
        } else {
                /* The worst case. */
-               mtu += 2 + blksize;
+               u32 padsize = ((blksize - 1) & 7) + 1;
+               mtu = ALIGN(mtu + 2, padsize) + blksize - padsize;
        }
        if (esp->conf.padlen)
-               mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+               mtu = ALIGN(mtu, esp->conf.padlen);
 
        return mtu + x->props.header_len + esp->auth.icv_full_len;
 }
index 2da514b16d95e724d6b0f42b46bc7f642a94aef4..b03e90649eb5f7517e437f40c95c55475e878680 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <linux/proc_fs.h>
+#include <linux/cpumask.h>
 
 #include <linux/netfilter_ipv6/ip6_tables.h>
 
@@ -950,8 +951,10 @@ translate_table(const char *name,
        }
 
        /* And one copy for every other CPU */
-       for (i = 1; i < num_possible_cpus(); i++) {
-               memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
+       for_each_cpu(i) {
+               if (i == 0)
+                       continue;
+               memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,
                       newinfo->entries,
                       SMP_ALIGN(newinfo->size));
        }
@@ -973,6 +976,7 @@ replace_table(struct ip6t_table *table,
                unsigned int i;
 
                for (i = 0; i < num_possible_cpus(); i++) {
+               for_each_cpu(i) {
                        table_base =
                                (void *)newinfo->entries
                                + TABLE_OFFSET(newinfo, i);
@@ -1019,7 +1023,7 @@ get_counters(const struct ip6t_table_info *t,
        unsigned int cpu;
        unsigned int i;
 
-       for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
+       for_each_cpu(cpu) {
                i = 0;
                IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
                                  t->size,
@@ -1153,7 +1157,8 @@ do_replace(void __user *user, unsigned int len)
                return -ENOMEM;
 
        newinfo = vmalloc(sizeof(struct ip6t_table_info)
-                         + SMP_ALIGN(tmp.size) * num_possible_cpus());
+                         + SMP_ALIGN(tmp.size) *
+                                       (highest_possible_processor_id()+1));
        if (!newinfo)
                return -ENOMEM;
 
@@ -1467,7 +1472,8 @@ int ip6t_register_table(struct ip6t_table *table,
                = { 0, 0, 0, { 0 }, { 0 }, { } };
 
        newinfo = vmalloc(sizeof(struct ip6t_table_info)
-                         + SMP_ALIGN(repl->size) * num_possible_cpus());
+                         + SMP_ALIGN(repl->size) *
+                                       (highest_possible_processor_id()+1));
        if (!newinfo)
                return -ENOMEM;
 
index 1caaca06f698bb3a1ae48377ea2e1dbcfc131dfe..4bc27a6334c169690650dd900031fde729b35b73 100644 (file)
@@ -133,7 +133,7 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
        memset(tb, 0, sizeof(struct nfattr *) * maxattr);
 
        while (NFA_OK(nfa, len)) {
-               unsigned flavor = nfa->nfa_type;
+               unsigned flavor = NFA_TYPE(nfa);
                if (flavor && flavor <= maxattr)
                        tb[flavor-1] = nfa;
                nfa = NFA_NEXT(nfa, len);
@@ -177,7 +177,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
                int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
 
                while (NFA_OK(attr, attrlen)) {
-                       unsigned flavor = attr->nfa_type;
+                       unsigned flavor = NFA_TYPE(attr);
                        if (flavor) {
                                if (flavor > attr_count)
                                        return -EINVAL;
index 45d3bc0812c8b270ea95e7a6c21799d6ec42273b..81510da317924841131c74ab5bd31fa6cfe9eb8a 100644 (file)
@@ -72,9 +72,11 @@ config NET_SCH_CLK_GETTIMEOFDAY
          Choose this if you need a high resolution clock source but can't use
          the CPU's cycle counter.
 
+# don't allow on SMP x86 because they can have unsynchronized TSCs.
+# gettimeofday is a good alternative
 config NET_SCH_CLK_CPU
        bool "CPU cycle counter"
-       depends on X86_TSC || X86_64 || ALPHA || SPARC64 || PPC64 || IA64
+       depends on ((X86_TSC || X86_64) && !SMP) || ALPHA || SPARC64 || PPC64 || IA64
        help
          Say Y here if you want to use the CPU's cycle counter as clock source.
          This is a cheap and high resolution clock source, but on some