]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge master.kernel.org:/home/rmk/linux-2.6-arm
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 13 Oct 2005 16:59:32 +0000 (09:59 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 13 Oct 2005 16:59:32 +0000 (09:59 -0700)
38 files changed:
arch/ppc/kernel/cputable.c
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
include/asm-powerpc/timex.h
include/asm-ppc/cputable.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/dccp/ccid.h
net/dccp/input.c
net/ipv4/esp4.c
net/ipv4/inet_timewait_sock.c
net/ipv4/netfilter/Kconfig
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/tcp_output.c
net/ipv6/esp6.c
net/netfilter/nfnetlink.c

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 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 4c942f71184daa9d69345404794dc82be834fa2c..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.      */
@@ -392,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
 
@@ -540,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
@@ -560,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 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 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 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 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 8225e4257258a13b5697c255290e5741dc642f0f..f37a50e55b6846eca00732da90c53aa7eeff2401 100644 (file)
@@ -435,7 +435,14 @@ 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)) {
+               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 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;