Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 20 Jun 2005 23:00:33 +0000 (16:00 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 20 Jun 2005 23:00:33 +0000 (16:00 -0700)
100 files changed:
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/common/dmabounce.c
arch/arm/common/sharpsl_param.c
arch/arm/configs/enp2611_defconfig
arch/arm/configs/ixdp2400_defconfig
arch/arm/configs/ixdp2401_defconfig
arch/arm/configs/ixdp2800_defconfig
arch/arm/configs/ixdp2801_defconfig
arch/arm/kernel/Makefile
arch/arm/kernel/arch.c [deleted file]
arch/arm/kernel/smp.c
arch/arm/lib/ashldi3.c
arch/arm/lib/ashrdi3.c
arch/arm/lib/gcclib.h
arch/arm/lib/longlong.h
arch/arm/lib/lshrdi3.c
arch/arm/lib/muldi3.c
arch/arm/lib/ucmpdi2.c
arch/arm/lib/udivdi3.c
arch/arm/mach-aaec2000/Kconfig [new file with mode: 0644]
arch/arm/mach-aaec2000/Makefile [new file with mode: 0644]
arch/arm/mach-aaec2000/aaed2000.c [new file with mode: 0644]
arch/arm/mach-aaec2000/core.c [new file with mode: 0644]
arch/arm/mach-aaec2000/core.h [new file with mode: 0644]
arch/arm/mach-integrator/core.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-versatile/Makefile
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/pci.c [new file with mode: 0644]
arch/arm/mm/Kconfig
arch/arm/mm/copypage-v6.c
arch/arm/mm/fault-armv.c
arch/arm/mm/flush.c
arch/arm/mm/ioremap.c
arch/ppc64/kernel/iommu.c
arch/ppc64/kernel/pSeries_smp.c
arch/ppc64/kernel/rtasd.c
drivers/char/watchdog/ixp2000_wdt.c
drivers/fc4/fc.c
drivers/scsi/aic7xxx/aic79xx_osm.c
include/asm-arm/arch-aaec2000/aaec2000.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-aaec2000/dma.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-aaec2000/hardware.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/io.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/irqs.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/memory.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/param.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/system.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/timex.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-aaec2000/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-ixp2000/ixp2000-regs.h
include/asm-arm/arch-versatile/hardware.h
include/asm-arm/arch-versatile/io.h
include/asm-arm/arch-versatile/platform.h
include/asm-arm/cacheflush.h
include/asm-arm/io.h
include/linux/atalk.h
include/linux/netlink.h
include/linux/pfkeyv2.h
include/linux/xfrm.h
include/net/ax25.h
include/net/ip_fib.h
include/net/sctp/command.h
include/net/sctp/constants.h
include/net/sctp/sctp.h
include/net/sctp/sm.h
include/net/sctp/structs.h
include/net/sctp/user.h
include/net/xfrm.h
net/appletalk/aarp.c
net/appletalk/ddp.c
net/ipv4/ah4.c
net/ipv4/esp4.c
net/ipv4/fib_frontend.c
net/ipv4/ipcomp.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_state.c
net/ipv4/xfrm4_tunnel.c
net/ipv6/ah6.c
net/ipv6/esp6.c
net/ipv6/ipcomp6.c
net/ipv6/xfrm6_tunnel.c
net/key/af_key.c
net/sctp/associola.c
net/sctp/endpointola.c
net/sctp/input.c
net/sctp/outqueue.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/sm_statetable.c
net/sctp/socket.c
net/sctp/transport.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c

index 475950c8a8317ec435f441137e4357d35efc93c1..ee8a9ad7bbd95343f46cd20e9467e062eaf848f2 100644 (file)
@@ -67,10 +67,6 @@ config GENERIC_BUST_SPINLOCK
 config GENERIC_ISA_DMA
        bool
 
-config GENERIC_IOMAP
-       bool
-       default y
-
 config FIQ
        bool
 
@@ -202,6 +198,11 @@ config ARCH_H720X
        help
          This enables support for systems based on the Hynix HMS720x
 
+config ARCH_AAEC2000
+       bool "Agilent AAEC-2000 based"
+       help
+         This enables support for systems based on the Agilent AAEC-2000
+
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -234,6 +235,8 @@ source "arch/arm/mach-h720x/Kconfig"
 
 source "arch/arm/mach-versatile/Kconfig"
 
+source "arch/arm/mach-aaec2000/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
        bool
@@ -277,7 +280,7 @@ config ISA_DMA_API
        default y
 
 config PCI
-       bool "PCI support" if ARCH_INTEGRATOR_AP
+       bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
index 2277e3d179cc79ea84e12fc72e0676cbb9e6f46d..8330495e2448bc33f2ad7236b4fb5e4a45ebb2a1 100644 (file)
@@ -97,6 +97,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
  machine-$(CONFIG_ARCH_VERSATILE)  := versatile
  machine-$(CONFIG_ARCH_IMX)       := imx
  machine-$(CONFIG_ARCH_H720X)     := h720x
+ machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
index 5797b1b100a1bc707031a3d7f169658261f4fe36..9d63a01214ebce2941a7033f41d49a059825a0fc 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/dmapool.h>
 #include <linux/list.h>
 
+#include <asm/cacheflush.h>
+
 #undef DEBUG
 
 #undef STATS
@@ -302,12 +304,24 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 
                DO_STATS ( device_info->bounce_count++ );
 
-               if ((dir == DMA_FROM_DEVICE) ||
-                   (dir == DMA_BIDIRECTIONAL)) {
+               if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+                       unsigned long ptr;
+
                        dev_dbg(dev,
                                "%s: copy back safe %p to unsafe %p size %d\n",
                                __func__, buf->safe, buf->ptr, size);
                        memcpy(buf->ptr, buf->safe, size);
+
+                       /*
+                        * DMA buffers must have the same cache properties
+                        * as if they were really used for DMA - which means
+                        * data must be written back to RAM.  Note that
+                        * we don't use dmac_flush_range() here for the
+                        * bidirectional case because we know the cache
+                        * lines will be coherent with the data written.
+                        */
+                       ptr = (unsigned long)buf->ptr;
+                       dmac_clean_range(ptr, ptr + size);
                }
                free_safe_buffer(device_info, buf);
        }
index c2c557a224c2af0b7c558263e920f42868795cf0..c94864c5b1af568ae3fb796f6790d4f4850de283 100644 (file)
@@ -22,7 +22,7 @@
  * them early in the boot process, then pass them to the appropriate drivers.
  * Not all devices use all paramaters but the format is common to all.
  */
-#ifdef ARCH_SA1100
+#ifdef CONFIG_ARCH_SA1100
 #define PARAM_BASE     0xe8ffc000
 #else
 #define PARAM_BASE     0xa0000a00
index e8f9fccffe84a02809fd5f40306ac712d4da09bf..06fae4b62774659a1b6389db4a1a5d56f5a088c2 100644 (file)
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
index 4fd663ecbe39085376bfdefeea608723cee85e5d..810a450a55d22a4c1dbcc139688f937aafab9db8 100644 (file)
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
index 6f51c98084a3500727de6283825cbf7c58a7efbe..72e1b940e975b858769ac25ce0556dee0b0d0c62 100644 (file)
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
index 7be3521f91fc85e27053fd4fb922021dc058e45d..1592e45f027839e7967ef26c17e79bdc44bd1f64 100644 (file)
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
index cd84a20f30f1e79b327466410d9b75b77802e551..f1afe3d09ec66c5797ed553f1de4d1c1138396ed 100644 (file)
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # System Type
index 4a2af55e134bcdc2cb07f01fc45d85458c673d94..3e1b0327e4d7a3a9bc25920eb98f6c5ab43c4b81 100644 (file)
@@ -6,7 +6,7 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 
 # Object file lists.
 
-obj-y          := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o   \
+obj-y          := compat.o dma.o entry-armv.o entry-common.o irq.o \
                   process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
                   time.o traps.o
 
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
deleted file mode 100644 (file)
index 4e02fbe..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  linux/arch/arm/kernel/arch.c
- *
- *  Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/elf.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/mach/arch.h>
-
-unsigned int vram_size;
-
-#ifdef CONFIG_ARCH_ACORN
-
-unsigned int memc_ctrl_reg;
-unsigned int number_mfm_drives;
-
-static int __init parse_tag_acorn(const struct tag *tag)
-{
-       memc_ctrl_reg = tag->u.acorn.memc_control_reg;
-       number_mfm_drives = tag->u.acorn.adfsdrives;
-
-       switch (tag->u.acorn.vram_pages) {
-       case 512:
-               vram_size += PAGE_SIZE * 256;
-       case 256:
-               vram_size += PAGE_SIZE * 256;
-       default:
-               break;
-       }
-#if 0
-       if (vram_size) {
-               desc->video_start = 0x02000000;
-               desc->video_end   = 0x02000000 + vram_size;
-       }
-#endif
-       return 0;
-}
-
-__tagtable(ATAG_ACORN, parse_tag_acorn);
-
-#endif
index 45ed036336e0534eb8b9bb9ecf57fe4861fd6875..34892758f098c485f0b47e97083daf699a399878 100644 (file)
@@ -145,7 +145,8 @@ int __init __cpu_up(unsigned int cpu)
        pgd_free(pgd);
 
        if (ret) {
-               printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
+               printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
+
                /*
                 * FIXME: We need to clean up the new idle thread. --rmk
                 */
index 130f5a8396695b758180c0856b336a0d7814ac18..b62875cfd8f842fdc85c4e32ee9769b93fef920c 100644 (file)
@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA.  */
 
 #include "gcclib.h"
 
-DItype
-__ashldi3 (DItype u, word_type b)
+s64 __ashldi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.low = 0;
-      w.s.high = (USItype)uu.s.low << -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.low >> bm;
-      w.s.low = (USItype)uu.s.low << b;
-      w.s.high = ((USItype)uu.s.high << b) | carries;
-    }
-
-  return w.ll;
+       DIunion w;
+       int bm;
+       DIunion uu;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+
+       bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+       if (bm <= 0) {
+               w.s.low = 0;
+               w.s.high = (u32) uu.s.low << -bm;
+       } else {
+               u32 carries = (u32) uu.s.low >> bm;
+               w.s.low = (u32) uu.s.low << b;
+               w.s.high = ((u32) uu.s.high << b) | carries;
+       }
+
+       return w.ll;
 }
-
index 71625d218f8d391266c2fd8b421e87838f2c6f33..9a8600a7543faf8159d029bf5b2dce40c8802852 100644 (file)
@@ -31,31 +31,27 @@ Boston, MA 02111-1307, USA.  */
 
 #include "gcclib.h"
 
-DItype
-__ashrdi3 (DItype u, word_type b)
+s64 __ashrdi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      /* w.s.high = 1..1 or 0..0 */
-      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
-      w.s.low = uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
-
-  return w.ll;
+       DIunion w;
+       int bm;
+       DIunion uu;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+
+       bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+       if (bm <= 0) {
+               /* w.s.high = 1..1 or 0..0 */
+               w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
+               w.s.low = uu.s.high >> -bm;
+       } else {
+               u32 carries = (u32) uu.s.high << bm;
+               w.s.high = uu.s.high >> b;
+               w.s.low = ((u32) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
 }
index 65314a3d9e273e932be1e1a3316b25f278d9f05f..8b6dcc656de779c3b2d030f0577238fe59e41954 100644 (file)
@@ -1,25 +1,22 @@
 /* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
 /* I Molton     29/07/01 */
 
-#define BITS_PER_UNIT  8
-#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#include <linux/types.h>
 
-typedef unsigned int UQItype    __attribute__ ((mode (QI)));
-typedef          int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype    __attribute__ ((mode (SI)));
-typedef          int DItype     __attribute__ ((mode (DI)));
-typedef          int word_type         __attribute__ ((mode (__word__)));
-typedef unsigned int UDItype    __attribute__ ((mode (DI)));
+#define BITS_PER_UNIT  8
+#define SI_TYPE_SIZE   (sizeof(s32) * BITS_PER_UNIT)
 
 #ifdef __ARMEB__
-  struct DIstruct {SItype high, low;};
+struct DIstruct {
+       s32 high, low;
+};
 #else
-  struct DIstruct {SItype low, high;};
+struct DIstruct {
+       s32 low, high;
+};
 #endif
 
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
+typedef union {
+       struct DIstruct s;
+       s64 ll;
 } DIunion;
-
index 179eea4edc35cc3a1180214cad63ca7e2ef807de..90ae647e4d76dadf575c4395e87affce807f0e19 100644 (file)
 
 #define __BITS4 (SI_TYPE_SIZE / 4)
 #define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
-#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+#define __ll_lowpart(t) ((u32) (t) % __ll_B)
+#define __ll_highpart(t) ((u32) (t) / __ll_B)
 
 /* Define auxiliary asm macros.
 
    1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
-   multiplies two USItype integers MULTIPLER and MULTIPLICAND,
-   and generates a two-part USItype product in HIGH_PROD and
+   multiplies two u32 integers MULTIPLER and MULTIPLICAND,
+   and generates a two-part u32 product in HIGH_PROD and
    LOW_PROD.
 
-   2) __umulsidi3(a,b) multiplies two USItype integers A and B,
-   and returns a UDItype product.  This is just a variant of umul_ppmm.
+   2) __umulsidi3(a,b) multiplies two u32 integers A and B,
+   and returns a u64 product.  This is just a variant of umul_ppmm.
 
    3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
    denominator) divides a two-word unsigned integer, composed by the
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
   __asm__ ("adds       %1, %4, %5                                      \n\
        adc     %0, %2, %3"                                             \
-          : "=r" ((USItype) (sh)),                                     \
-            "=&r" ((USItype) (sl))                                     \
-          : "%r" ((USItype) (ah)),                                     \
-            "rI" ((USItype) (bh)),                                     \
-            "%r" ((USItype) (al)),                                     \
-            "rI" ((USItype) (bl)))
+          : "=r" ((u32) (sh)),                                 \
+            "=&r" ((u32) (sl))                                 \
+          : "%r" ((u32) (ah)),                                 \
+            "rI" ((u32) (bh)),                                 \
+            "%r" ((u32) (al)),                                 \
+            "rI" ((u32) (bl)))
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
   __asm__ ("subs       %1, %4, %5                                      \n\
        sbc     %0, %2, %3"                                             \
-          : "=r" ((USItype) (sh)),                                     \
-            "=&r" ((USItype) (sl))                                     \
-          : "r" ((USItype) (ah)),                                      \
-            "rI" ((USItype) (bh)),                                     \
-            "r" ((USItype) (al)),                                      \
-            "rI" ((USItype) (bl)))
+          : "=r" ((u32) (sh)),                                 \
+            "=&r" ((u32) (sl))                                 \
+          : "r" ((u32) (ah)),                                  \
+            "rI" ((u32) (bh)),                                 \
+            "r" ((u32) (al)),                                  \
+            "rI" ((u32) (bl)))
 #define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2;                                    \
+{register u32 __t0, __t1, __t2;                                        \
   __asm__ ("%@ Inlined umul_ppmm                                       \n\
        mov     %2, %5, lsr #16                                         \n\
        mov     %0, %6, lsr #16                                         \n\
        addcs   %0, %0, #65536                                          \n\
        adds    %1, %1, %3, lsl #16                                     \n\
        adc     %0, %0, %3, lsr #16"                                    \
-          : "=&r" ((USItype) (xh)),                                    \
-            "=r" ((USItype) (xl)),                                     \
+          : "=&r" ((u32) (xh)),                                        \
+            "=r" ((u32) (xl)),                                 \
             "=&r" (__t0), "=&r" (__t1), "=r" (__t2)                    \
-          : "r" ((USItype) (a)),                                       \
-            "r" ((USItype) (b)));}
+          : "r" ((u32) (a)),                                   \
+            "r" ((u32) (b)));}
 #define UMUL_TIME 20
 #define UDIV_TIME 100
-#endif /* __arm__ */
+#endif                         /* __arm__ */
 
 #define __umulsidi3(u, v) \
   ({DIunion __w;                                                       \
 
 #define __udiv_qrnnd_c(q, r, n1, n0, d) \
   do {                                                                 \
-    USItype __d1, __d0, __q1, __q0;                                    \
-    USItype __r1, __r0, __m;                                           \
+    u32 __d1, __d0, __q1, __q0;                                        \
+    u32 __r1, __r0, __m;                                               \
     __d1 = __ll_highpart (d);                                          \
     __d0 = __ll_lowpart (d);                                           \
                                                                        \
     __r1 = (n1) % __d1;                                                        \
     __q1 = (n1) / __d1;                                                        \
-    __m = (USItype) __q1 * __d0;                                       \
+    __m = (u32) __q1 * __d0;                                   \
     __r1 = __r1 * __ll_B | __ll_highpart (n0);                         \
     if (__r1 < __m)                                                    \
       {                                                                        \
                                                                        \
     __r0 = __r1 % __d1;                                                        \
     __q0 = __r1 / __d1;                                                        \
-    __m = (USItype) __q0 * __d0;                                       \
+    __m = (u32) __q0 * __d0;                                   \
     __r0 = __r0 * __ll_B | __ll_lowpart (n0);                          \
     if (__r0 < __m)                                                    \
       {                                                                        \
       }                                                                        \
     __r0 -= __m;                                                       \
                                                                        \
-    (q) = (USItype) __q1 * __ll_B | __q0;                              \
+    (q) = (u32) __q1 * __ll_B | __q0;                          \
     (r) = __r0;                                                                \
   } while (0)
 
 
 #define count_leading_zeros(count, x) \
   do {                                                                 \
-    USItype __xr = (x);                                                        \
-    USItype __a;                                                       \
+    u32 __xr = (x);                                                    \
+    u32 __a;                                                   \
                                                                        \
     if (SI_TYPE_SIZE <= 32)                                            \
       {                                                                        \
-       __a = __xr < ((USItype)1<<2*__BITS4)                            \
-         ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4)                \
-         : (__xr < ((USItype)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);  \
+       __a = __xr < ((u32)1<<2*__BITS4)                                \
+         ? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4)            \
+         : (__xr < ((u32)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);      \
       }                                                                        \
     else                                                               \
       {                                                                        \
index b666f1bad451047adcdf348ab2fd105d482b496f..3681f49d2b6e24c43c3d4b1670e57f2f50ebb1dd 100644 (file)
@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA.  */
 
 #include "gcclib.h"
 
-DItype
-__lshrdi3 (DItype u, word_type b)
+s64 __lshrdi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.high = 0;
-      w.s.low = (USItype)uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = (USItype)uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
-
-  return w.ll;
+       DIunion w;
+       int bm;
+       DIunion uu;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+
+       bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+       if (bm <= 0) {
+               w.s.high = 0;
+               w.s.low = (u32) uu.s.high >> -bm;
+       } else {
+               u32 carries = (u32) uu.s.high << bm;
+               w.s.high = (u32) uu.s.high >> b;
+               w.s.low = ((u32) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
 }
-
index 44d611b1cfdbda4fcfdd5b17d0586109b249bb4a..0a3b93313f1831b24ef778f595a9d9bca0571a93 100644 (file)
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA.  */
 #include "gcclib.h"
 
 #define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2;                                     \
+{register u32 __t0, __t1, __t2;                                     \
   __asm__ ("%@ Inlined umul_ppmm                                       \n\
         mov     %2, %5, lsr #16                                                \n\
         mov     %0, %6, lsr #16                                                \n\
@@ -46,32 +46,27 @@ Boston, MA 02111-1307, USA.  */
         addcs   %0, %0, #65536                                         \n\
         adds    %1, %1, %3, lsl #16                                    \n\
         adc     %0, %0, %3, lsr #16"                                    \
-           : "=&r" ((USItype) (xh)),                                    \
-             "=r" ((USItype) (xl)),                                     \
+           : "=&r" ((u32) (xh)),                                    \
+             "=r" ((u32) (xl)),                                     \
              "=&r" (__t0), "=&r" (__t1), "=r" (__t2)                    \
-           : "r" ((USItype) (a)),                                       \
-             "r" ((USItype) (b)));}
-
+           : "r" ((u32) (a)),                                       \
+             "r" ((u32) (b)));}
 
 #define __umulsidi3(u, v) \
   ({DIunion __w;                                                        \
     umul_ppmm (__w.s.high, __w.s.low, u, v);                            \
     __w.ll; })
 
-
-DItype
-__muldi3 (DItype u, DItype v)
+s64 __muldi3(s64 u, s64 v)
 {
-  DIunion w;
-  DIunion uu, vv;
+       DIunion w;
+       DIunion uu, vv;
 
-  uu.ll = u,
-  vv.ll = v;
+       uu.ll = u, vv.ll = v;
 
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-               + (USItype) uu.s.high * (USItype) vv.s.low);
+       w.ll = __umulsidi3(uu.s.low, vv.s.low);
+       w.s.high += ((u32) uu.s.low * (u32) vv.s.high
+                    + (u32) uu.s.high * (u32) vv.s.low);
 
-  return w.ll;
+       return w.ll;
 }
-
index 6c6ae63efa0254cb75476231d83cffc0ad34d7ef..57f3f2df3850147286d89f870912cf40486d2d66 100644 (file)
@@ -31,21 +31,19 @@ Boston, MA 02111-1307, USA.  */
 
 #include "gcclib.h"
 
-word_type
-__ucmpdi2 (DItype a, DItype b)
+int __ucmpdi2(s64 a, s64 b)
 {
-  DIunion au, bu;
-
-  au.ll = a, bu.ll = b;
-
-  if ((USItype) au.s.high < (USItype) bu.s.high)
-    return 0;
-  else if ((USItype) au.s.high > (USItype) bu.s.high)
-    return 2;
-  if ((USItype) au.s.low < (USItype) bu.s.low)
-    return 0;
-  else if ((USItype) au.s.low > (USItype) bu.s.low)
-    return 2;
-  return 1;
+       DIunion au, bu;
+
+       au.ll = a, bu.ll = b;
+
+       if ((u32) au.s.high < (u32) bu.s.high)
+               return 0;
+       else if ((u32) au.s.high > (u32) bu.s.high)
+               return 2;
+       if ((u32) au.s.low < (u32) bu.s.low)
+               return 0;
+       else if ((u32) au.s.low > (u32) bu.s.low)
+               return 2;
+       return 1;
 }
-
index d25195f673f465074a96cbb1ec30f1af6f65d1b3..e343be4c66421c9b6d2524f11e7858b02db369f9 100644 (file)
@@ -32,211 +32,191 @@ Boston, MA 02111-1307, USA.  */
 #include "gcclib.h"
 #include "longlong.h"
 
-static const UQItype __clz_tab[] =
-{
-  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+static const u8 __clz_tab[] = {
+       0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+           5, 5, 5, 5, 5, 5, 5, 5,
+       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+           6, 6, 6, 6, 6, 6, 6, 6,
+       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+           7, 7, 7, 7, 7, 7, 7, 7,
+       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+           7, 7, 7, 7, 7, 7, 7, 7,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
+       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+           8, 8, 8, 8, 8, 8, 8, 8,
 };
 
-UDItype
-__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
+u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
 {
-  DIunion ww;
-  DIunion nn, dd;
-  DIunion rr;
-  USItype d0, d1, n0, n1, n2;
-  USItype q0, q1;
-  USItype b, bm;
-
-  nn.ll = n;
-  dd.ll = d;
-
-  d0 = dd.s.low;
-  d1 = dd.s.high;
-  n0 = nn.s.low;
-  n1 = nn.s.high;
-
-  if (d1 == 0)
-    {
-      if (d0 > n1)
-        {
-          /* 0q = nn / 0D */
-
-          count_leading_zeros (bm, d0);
-
-          if (bm != 0)
-            {
-              /* Normalize, i.e. make the most significant bit of the
-                 denominator set.  */
-
-              d0 = d0 << bm;
-              n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
-              n0 = n0 << bm;
-            }
-
-          udiv_qrnnd (q0, n0, n1, n0, d0);
-          q1 = 0;
-
-          /* Remainder in n0 >> bm.  */
-        }
-      else
-        {
-          /* qq = NN / 0d */
-
-          if (d0 == 0)
-            d0 = 1 / d0;        /* Divide intentionally by zero.  */
-
-          count_leading_zeros (bm, d0);
-
-          if (bm == 0)
-            {
-              /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
-                 conclude (the most significant bit of n1 is set) /\ (the
-                 leading quotient digit q1 = 1).
-
-                 This special case is necessary, not an optimization.
-                 (Shifts counts of SI_TYPE_SIZE are undefined.)  */
-
-              n1 -= d0;
-              q1 = 1;
-            }
-          else
-            {
-              /* Normalize.  */
-
-              b = SI_TYPE_SIZE - bm;
-
-              d0 = d0 << bm;
-              n2 = n1 >> b;
-              n1 = (n1 << bm) | (n0 >> b);
-              n0 = n0 << bm;
-
-              udiv_qrnnd (q1, n1, n2, n1, d0);
-            }
-
-          /* n1 != d0...  */
-
-          udiv_qrnnd (q0, n0, n1, n0, d0);
-
-          /* Remainder in n0 >> bm.  */
-        }
-
-      if (rp != 0)
-        {
-          rr.s.low = n0 >> bm;
-          rr.s.high = 0;
-          *rp = rr.ll;
-        }
-    }
-  else
-    {
-      if (d1 > n1)
-        {
-          /* 00 = nn / DD */
-
-          q0 = 0;
-          q1 = 0;
-
-          /* Remainder in n1n0.  */
-          if (rp != 0)
-            {
-              rr.s.low = n0;
-              rr.s.high = n1;
-              *rp = rr.ll;
-            }
-        }
-      else
-        {
-          /* 0q = NN / dd */
-
-          count_leading_zeros (bm, d1);
-          if (bm == 0)
-            {
-              /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
-                 conclude (the most significant bit of n1 is set) /\ (the
-                 quotient digit q0 = 0 or 1).
-
-                 This special case is necessary, not an optimization.  */
-
-              /* The condition on the next line takes advantage of that
-                 n1 >= d1 (true due to program flow).  */
-              if (n1 > d1 || n0 >= d0)
-                {
-                  q0 = 1;
-                  sub_ddmmss (n1, n0, n1, n0, d1, d0);
-                }
-              else
-                q0 = 0;
-
-              q1 = 0;
-
-              if (rp != 0)
-                {
-                  rr.s.low = n0;
-                  rr.s.high = n1;
-                  *rp = rr.ll;
-                }
-            }
-          else
-            {
-              USItype m1, m0;
-              /* Normalize.  */
-
-              b = SI_TYPE_SIZE - bm;
-
-              d1 = (d1 << bm) | (d0 >> b);
-              d0 = d0 << bm;
-              n2 = n1 >> b;
-              n1 = (n1 << bm) | (n0 >> b);
-              n0 = n0 << bm;
-
-              udiv_qrnnd (q0, n1, n2, n1, d1);
-              umul_ppmm (m1, m0, q0, d0);
-
-              if (m1 > n1 || (m1 == n1 && m0 > n0))
-                {
-                  q0--;
-                  sub_ddmmss (m1, m0, m1, m0, d1, d0);
-                }
-
-              q1 = 0;
-
-              /* Remainder in (n1n0 - m1m0) >> bm.  */
-              if (rp != 0)
-                {
-                  sub_ddmmss (n1, n0, n1, n0, m1, m0);
-                  rr.s.low = (n1 << b) | (n0 >> bm);
-                  rr.s.high = n1 >> bm;
-                  *rp = rr.ll;
-                }
-            }
-        }
-    }
-
-  ww.s.low = q0;
-  ww.s.high = q1;
-  return ww.ll;
+       DIunion ww;
+       DIunion nn, dd;
+       DIunion rr;
+       u32 d0, d1, n0, n1, n2;
+       u32 q0, q1;
+       u32 b, bm;
+
+       nn.ll = n;
+       dd.ll = d;
+
+       d0 = dd.s.low;
+       d1 = dd.s.high;
+       n0 = nn.s.low;
+       n1 = nn.s.high;
+
+       if (d1 == 0) {
+               if (d0 > n1) {
+                       /* 0q = nn / 0D */
+
+                       count_leading_zeros(bm, d0);
+
+                       if (bm != 0) {
+                               /* Normalize, i.e. make the most significant bit of the
+                                  denominator set.  */
+
+                               d0 = d0 << bm;
+                               n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
+                               n0 = n0 << bm;
+                       }
+
+                       udiv_qrnnd(q0, n0, n1, n0, d0);
+                       q1 = 0;
+
+                       /* Remainder in n0 >> bm.  */
+               } else {
+                       /* qq = NN / 0d */
+
+                       if (d0 == 0)
+                               d0 = 1 / d0;    /* Divide intentionally by zero.  */
+
+                       count_leading_zeros(bm, d0);
+
+                       if (bm == 0) {
+                               /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+                                  conclude (the most significant bit of n1 is set) /\ (the
+                                  leading quotient digit q1 = 1).
+
+                                  This special case is necessary, not an optimization.
+                                  (Shifts counts of SI_TYPE_SIZE are undefined.)  */
+
+                               n1 -= d0;
+                               q1 = 1;
+                       } else {
+                               /* Normalize.  */
+
+                               b = SI_TYPE_SIZE - bm;
+
+                               d0 = d0 << bm;
+                               n2 = n1 >> b;
+                               n1 = (n1 << bm) | (n0 >> b);
+                               n0 = n0 << bm;
+
+                               udiv_qrnnd(q1, n1, n2, n1, d0);
+                       }
+
+                       /* n1 != d0...  */
+
+                       udiv_qrnnd(q0, n0, n1, n0, d0);
+
+                       /* Remainder in n0 >> bm.  */
+               }
+
+               if (rp != 0) {
+                       rr.s.low = n0 >> bm;
+                       rr.s.high = 0;
+                       *rp = rr.ll;
+               }
+       } else {
+               if (d1 > n1) {
+                       /* 00 = nn / DD */
+
+                       q0 = 0;
+                       q1 = 0;
+
+                       /* Remainder in n1n0.  */
+                       if (rp != 0) {
+                               rr.s.low = n0;
+                               rr.s.high = n1;
+                               *rp = rr.ll;
+                       }
+               } else {
+                       /* 0q = NN / dd */
+
+                       count_leading_zeros(bm, d1);
+                       if (bm == 0) {
+                               /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+                                  conclude (the most significant bit of n1 is set) /\ (the
+                                  quotient digit q0 = 0 or 1).
+
+                                  This special case is necessary, not an optimization.  */
+
+                               /* The condition on the next line takes advantage of that
+                                  n1 >= d1 (true due to program flow).  */
+                               if (n1 > d1 || n0 >= d0) {
+                                       q0 = 1;
+                                       sub_ddmmss(n1, n0, n1, n0, d1, d0);
+                               } else
+                                       q0 = 0;
+
+                               q1 = 0;
+
+                               if (rp != 0) {
+                                       rr.s.low = n0;
+                                       rr.s.high = n1;
+                                       *rp = rr.ll;
+                               }
+                       } else {
+                               u32 m1, m0;
+                               /* Normalize.  */
+
+                               b = SI_TYPE_SIZE - bm;
+
+                               d1 = (d1 << bm) | (d0 >> b);
+                               d0 = d0 << bm;
+                               n2 = n1 >> b;
+                               n1 = (n1 << bm) | (n0 >> b);
+                               n0 = n0 << bm;
+
+                               udiv_qrnnd(q0, n1, n2, n1, d1);
+                               umul_ppmm(m1, m0, q0, d0);
+
+                               if (m1 > n1 || (m1 == n1 && m0 > n0)) {
+                                       q0--;
+                                       sub_ddmmss(m1, m0, m1, m0, d1, d0);
+                               }
+
+                               q1 = 0;
+
+                               /* Remainder in (n1n0 - m1m0) >> bm.  */
+                               if (rp != 0) {
+                                       sub_ddmmss(n1, n0, n1, n0, m1, m0);
+                                       rr.s.low = (n1 << b) | (n0 >> bm);
+                                       rr.s.high = n1 >> bm;
+                                       *rp = rr.ll;
+                               }
+                       }
+               }
+       }
+
+       ww.s.low = q0;
+       ww.s.high = q1;
+       return ww.ll;
 }
 
-UDItype
-__udivdi3 (UDItype n, UDItype d)
+u64 __udivdi3(u64 n, u64 d)
 {
-  return __udivmoddi4 (n, d, (UDItype *) 0);
+       return __udivmoddi4(n, d, (u64 *) 0);
 }
 
-UDItype
-__umoddi3 (UDItype u, UDItype v)
+u64 __umoddi3(u64 u, u64 v)
 {
-  UDItype w;
+       u64 w;
 
-  (void) __udivmoddi4 (u ,v, &w);
+       (void)__udivmoddi4(u, v, &w);
 
-  return w;
+       return w;
 }
-
diff --git a/arch/arm/mach-aaec2000/Kconfig b/arch/arm/mach-aaec2000/Kconfig
new file mode 100644 (file)
index 0000000..5e4bef9
--- /dev/null
@@ -0,0 +1,11 @@
+if ARCH_AAEC2000
+
+menu "Agilent AAEC-2000 Implementations"
+
+config MACH_AAED2000
+       bool "Agilent AAED-2000 Development Platform"
+       select CPU_ARM920T
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile
new file mode 100644 (file)
index 0000000..20ec838
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support (must be linked before board specific support)
+obj-y += core.o
+
+# Specific board support
+obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
new file mode 100644 (file)
index 0000000..5417ca3
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/aaed2000.c
+ *
+ *  Support for the Agilent AAED-2000 Development Platform.
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "core.h"
+
+static void __init aaed2000_init_irq(void)
+{
+       aaec2000_init_irq();
+}
+
+static void __init aaed2000_map_io(void)
+{
+       aaec2000_map_io();
+}
+
+MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
+       MAINTAINER("Nicolas Bellido Y Ortega")
+       BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE)
+       MAPIO(aaed2000_map_io)
+       INITIRQ(aaed2000_init_irq)
+       .timer          = &aaec2000_timer,
+MACHINE_END
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
new file mode 100644 (file)
index 0000000..fc145b3
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/core.c
+ *
+ *  Code common to all AAEC-2000 machines
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/signal.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+/*
+ * Common I/O mapping:
+ *
+ * Static virtual address mappings are as follow:
+ *
+ * 0xf8000000-0xf8001ffff: Devices connected to APB bus
+ * 0xf8002000-0xf8003ffff: Devices connected to AHB bus
+ *
+ * Below 0xe8000000 is reserved for vm allocation.
+ *
+ * The machine specific code must provide the extra mapping beside the
+ * default mapping provided here.
+ */
+static struct map_desc standard_io_desc[] __initdata = {
+ /* virtual         physical       length           type */
+  { VIO_APB_BASE,   PIO_APB_BASE,  IO_APB_LENGTH,   MT_DEVICE },
+  { VIO_AHB_BASE,   PIO_AHB_BASE,  IO_AHB_LENGTH,   MT_DEVICE }
+};
+
+void __init aaec2000_map_io(void)
+{
+       iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
+
+/*
+ * Interrupt handling routines
+ */
+static void aaec2000_int_ack(unsigned int irq)
+{
+       IRQ_INTSR = 1 << irq;
+}
+
+static void aaec2000_int_mask(unsigned int irq)
+{
+       IRQ_INTENC |= (1 << irq);
+}
+
+static void aaec2000_int_unmask(unsigned int irq)
+{
+       IRQ_INTENS |= (1 << irq);
+}
+
+static struct irqchip aaec2000_irq_chip = {
+       .ack    = aaec2000_int_ack,
+       .mask   = aaec2000_int_mask,
+       .unmask = aaec2000_int_unmask,
+};
+
+void __init aaec2000_init_irq(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < NR_IRQS; i++) {
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_chip(i, &aaec2000_irq_chip);
+               set_irq_flags(i, IRQF_VALID);
+       }
+
+       /* Disable all interrupts */
+       IRQ_INTENC = 0xffffffff;
+
+       /* Clear any pending interrupts */
+       IRQ_INTSR = IRQ_INTSR;
+}
+
+/*
+ * Time keeping
+ */
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long aaec2000_gettimeoffset(void)
+{
+       unsigned long ticks_to_match, elapsed, usec;
+
+       /* Get ticks before next timer match */
+       ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
+
+       /* We need elapsed ticks since last match */
+       elapsed = LATCH - ticks_to_match;
+
+       /* Now, convert them to usec */
+       usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
+
+       return usec;
+}
+
+/* We enter here with IRQs enabled */
+static irqreturn_t
+aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /* TODO: Check timer accuracy */
+       write_seqlock(&xtime_lock);
+
+       timer_tick(regs);
+       TIMER1_CLEAR = 1;
+
+       write_sequnlock(&xtime_lock);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction aaec2000_timer_irq = {
+       .name           = "AAEC-2000 Timer Tick",
+       .flags          = SA_INTERRUPT,
+       .handler        = aaec2000_timer_interrupt
+};
+
+static void __init aaec2000_timer_init(void)
+{
+       /* Disable timer 1 */
+       TIMER1_CTRL = 0;
+
+       /* We have somehow to generate a 100Hz clock.
+        * We then use the 508KHz timer in periodic mode.
+        */
+       TIMER1_LOAD = LATCH;
+       TIMER1_CLEAR = 1; /* Clear interrupt */
+
+       setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
+
+       TIMER1_CTRL = TIMER_CTRL_ENABLE |
+                       TIMER_CTRL_PERIODIC |
+                       TIMER_CTRL_CLKSEL_508K;
+}
+
+struct sys_timer aaec2000_timer = {
+       .init           = aaec2000_timer_init,
+       .offset         = aaec2000_gettimeoffset,
+};
+
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
new file mode 100644 (file)
index 0000000..91893d8
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/core.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+struct sys_timer;
+
+extern struct sys_timer aaec2000_timer;
+extern void __init aaec2000_map_io(void);
+extern void __init aaec2000_init_irq(void);
index d302f0405fd2fa3be49a4692fcc9af4a354946e1..bd1e5e3c9d34b2e055f6d12763e2735b3994daf4 100644 (file)
@@ -227,7 +227,6 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * primary CPU
         */
        if (hard_smp_processor_id() == 0) {
-               nmi_tick();
                timer_tick(regs);
 #ifdef CONFIG_SMP
                smp_send_timer();
index 4f3c3d5c781cae9790bdede88e260853f10d7f90..fc0555596d6d70c82a0c3cefb603efc9e574d2e7 100644 (file)
@@ -162,12 +162,13 @@ void __init ixp2000_map_io(void)
 static unsigned ticks_per_jiffy;
 static unsigned ticks_per_usec;
 static unsigned next_jiffy_time;
+static volatile unsigned long *missing_jiffy_timer_csr;
 
 unsigned long ixp2000_gettimeoffset (void)
 {
        unsigned long offset;
 
-       offset = next_jiffy_time - *IXP2000_T4_CSR;
+       offset = next_jiffy_time - *missing_jiffy_timer_csr;
 
        return offset / ticks_per_usec;
 }
@@ -179,7 +180,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        /* clear timer 1 */
        ixp2000_reg_write(IXP2000_T1_CLR, 1);
        
-       while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
+       while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
                timer_tick(regs);
                next_jiffy_time -= ticks_per_jiffy;
        }
@@ -197,20 +198,37 @@ static struct irqaction ixp2000_timer_irq = {
 
 void __init ixp2000_init_time(unsigned long tick_rate)
 {
-       ixp2000_reg_write(IXP2000_T1_CLR, 0);
-       ixp2000_reg_write(IXP2000_T4_CLR, 0);
-
        ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
        ticks_per_usec = tick_rate / 1000000;
 
+       /*
+        * We use timer 1 as our timer interrupt.
+        */
+       ixp2000_reg_write(IXP2000_T1_CLR, 0);
        ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
        ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
 
        /*
-        * We use T4 as a monotonic counter to track missed jiffies
+        * We use a second timer as a monotonic counter for tracking
+        * missed jiffies.  The IXP2000 has four timers, but if we're
+        * on an A-step IXP2800, timer 2 and 3 don't work, so on those
+        * chips we use timer 4.  Timer 4 is the only timer that can
+        * be used for the watchdog, so we use timer 2 if we're on a
+        * non-buggy chip.
         */
-       ixp2000_reg_write(IXP2000_T4_CLD, -1);
-       ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+       if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+               printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
+
+               ixp2000_reg_write(IXP2000_T4_CLR, 0);
+               ixp2000_reg_write(IXP2000_T4_CLD, -1);
+               ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+               missing_jiffy_timer_csr = IXP2000_T4_CSR;
+       } else {
+               ixp2000_reg_write(IXP2000_T2_CLR, 0);
+               ixp2000_reg_write(IXP2000_T2_CLD, -1);
+               ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
+               missing_jiffy_timer_csr = IXP2000_T2_CSR;
+       }
        next_jiffy_time = 0xffffffff;
 
        /* register for interrupt */
index 5d608837757a8247a9cbb11ed781102b8e166b5a..ba81e70ed813ac633ab18fb305cfde4680ed2848 100644 (file)
@@ -5,3 +5,4 @@
 obj-y                                  := core.o clock.o
 obj-$(CONFIG_ARCH_VERSATILE_PB)                += versatile_pb.o
 obj-$(CONFIG_MACH_VERSATILE_AB)                += versatile_ab.o
+obj-$(CONFIG_PCI)                      += pci.o
index 302c2a7b9b63745bbeae0f59cd49fad31c259435..6a7cbea5e098d4acf62a3966217a643656848a3b 100644 (file)
@@ -196,11 +196,15 @@ static struct map_desc versatile_io_desc[] __initdata = {
 #ifdef CONFIG_DEBUG_LL
  { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K,      MT_DEVICE },
 #endif
-#ifdef FIXME
- { PCI_MEMORY_VADDR,                PHYS_PCI_MEM_BASE,    SZ_16M,     MT_DEVICE },
- { PCI_CONFIG_VADDR,                PHYS_PCI_CONFIG_BASE, SZ_16M,     MT_DEVICE },
- { PCI_V3_VADDR,                    PHYS_PCI_V3_BASE,     SZ_512K,    MT_DEVICE },
- { PCI_IO_VADDR,                    PHYS_PCI_IO_BASE,     SZ_64K,     MT_DEVICE },
+#ifdef CONFIG_PCI
+ { IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
+ { VERSATILE_PCI_VIRT_BASE,          VERSATILE_PCI_BASE,   VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
+ { VERSATILE_PCI_CFG_VIRT_BASE,      VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
+#if 0
+ { VERSATILE_PCI_VIRT_MEM_BASE0,     VERSATILE_PCI_MEM_BASE0, SZ_16M,  MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE1,     VERSATILE_PCI_MEM_BASE1, SZ_16M,  MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE2,     VERSATILE_PCI_MEM_BASE2, SZ_16M,  MT_DEVICE },
+#endif
 #endif
 };
 
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
new file mode 100644 (file)
index 0000000..d1565e8
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ *  linux/arch/arm/mach-versatile/pci.c
+ *
+ * (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved.
+ * You can redistribute and/or modify this software under the terms of version 2
+ * of the GNU General Public License as published by the Free Software Foundation.
+ * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software.
+ *
+ * ARM Versatile PCI driver.
+ *
+ * 14/04/2005 Initial version, colin.king@philips.com
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * these spaces are mapped using the following base registers:
+ *
+ * Usage Local Bus Memory         Base/Map registers used
+ *
+ * Mem   50000000 - 5FFFFFFF      LB_BASE0/LB_MAP0,  non prefetch
+ * Mem   60000000 - 6FFFFFFF      LB_BASE1/LB_MAP1,  prefetch
+ * IO    44000000 - 4FFFFFFF      LB_BASE2/LB_MAP2,  IO
+ * Cfg   42000000 - 42FFFFFF     PCI config
+ *
+ */
+#define SYS_PCICTL                     IO_ADDRESS(VERSATILE_SYS_PCICTL)
+#define PCI_IMAP0                      IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
+#define PCI_IMAP1                      IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
+#define PCI_IMAP2                      IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
+#define PCI_SMAP0                      IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
+#define PCI_SMAP1                      IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
+#define PCI_SMAP2                      IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
+#define PCI_SELFID                     IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
+
+#define DEVICE_ID_OFFSET               0x00
+#define CSR_OFFSET                     0x04
+#define CLASS_ID_OFFSET                        0x08
+
+#define VP_PCI_DEVICE_ID               0x030010ee
+#define VP_PCI_CLASS_ID                        0x0b400000
+
+static unsigned long pci_slot_ignore = 0;
+
+static int __init versatile_pci_slot_ignore(char *str)
+{
+       int retval;
+       int slot;
+
+       while ((retval = get_option(&str,&slot))) {
+               if ((slot < 0) || (slot > 31)) {
+                       printk("Illegal slot value: %d\n",slot);
+               } else {
+                       pci_slot_ignore |= (1 << slot);
+               }
+       }
+       return 1;
+}
+
+__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
+
+
+static unsigned long __pci_addr(struct pci_bus *bus,
+                               unsigned int devfn, int offset)
+{
+       unsigned int busnr = bus->number;
+
+       /*
+        * Trap out illegal values
+        */
+       if (offset > 255)
+               BUG();
+       if (busnr > 255)
+               BUG();
+       if (devfn > 255)
+               BUG();
+
+       return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
+               (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
+}
+
+static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+                                int size, u32 *val)
+{
+       unsigned long addr = __pci_addr(bus, devfn, where);
+       u32 v;
+       int slot = PCI_SLOT(devfn);
+
+       if (pci_slot_ignore & (1 << slot)) {
+               /* Ignore this slot */
+               switch (size) {
+               case 1:
+                       v = 0xff;
+                       break;
+               case 2:
+                       v = 0xffff;
+                       break;
+               default:
+                       v = 0xffffffff;
+               }
+       } else {
+               switch (size) {
+               case 1:
+                       addr &= ~3;
+                       v = __raw_readb(addr);
+                       break;
+
+               case 2:
+                       v = __raw_readl(addr & ~3);
+                       if (addr & 2) v >>= 16;
+                       v &= 0xffff;
+                       break;
+
+               default:
+                       addr &= ~3;
+                       v = __raw_readl(addr);
+                       break;
+               }
+       }
+
+       *val = v;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+                                 int size, u32 val)
+{
+       unsigned long addr = __pci_addr(bus, devfn, where);
+       int slot = PCI_SLOT(devfn);
+
+       if (pci_slot_ignore & (1 << slot)) {
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       switch (size) {
+       case 1:
+               __raw_writeb((u8)val, addr);
+               break;
+
+       case 2:
+               __raw_writew((u16)val, addr);
+               break;
+
+       case 4:
+               __raw_writel(val, addr);
+               break;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_versatile_ops = {
+       .read   = versatile_read_config,
+       .write  = versatile_write_config,
+};
+
+static struct resource io_mem = {
+       .name   = "PCI I/O space",
+       .start  = VERSATILE_PCI_MEM_BASE0,
+       .end    = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
+       .flags  = IORESOURCE_IO,
+};
+
+static struct resource non_mem = {
+       .name   = "PCI non-prefetchable",
+       .start  = VERSATILE_PCI_MEM_BASE1,
+       .end    = VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct resource pre_mem = {
+       .name   = "PCI prefetchable",
+       .start  = VERSATILE_PCI_MEM_BASE2,
+       .end    = VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1,
+       .flags  = IORESOURCE_MEM | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_versatile_setup_resources(struct resource **resource)
+{
+       int ret = 0;
+
+       ret = request_resource(&iomem_resource, &io_mem);
+       if (ret) {
+               printk(KERN_ERR "PCI: unable to allocate I/O "
+                      "memory region (%d)\n", ret);
+               goto out;
+       }
+       ret = request_resource(&iomem_resource, &non_mem);
+       if (ret) {
+               printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
+                      "memory region (%d)\n", ret);
+               goto release_io_mem;
+       }
+       ret = request_resource(&iomem_resource, &pre_mem);
+       if (ret) {
+               printk(KERN_ERR "PCI: unable to allocate prefetchable "
+                      "memory region (%d)\n", ret);
+               goto release_non_mem;
+       }
+
+       /*
+        * bus->resource[0] is the IO resource for this bus
+        * bus->resource[1] is the mem resource for this bus
+        * bus->resource[2] is the prefetch mem resource for this bus
+        */
+       resource[0] = &io_mem;
+       resource[1] = &non_mem;
+       resource[2] = &pre_mem;
+
+       goto out;
+
+ release_non_mem:
+       release_resource(&non_mem);
+ release_io_mem:
+       release_resource(&io_mem);
+ out:
+       return ret;
+}
+
+int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
+{
+       int ret = 0;
+        int i;
+        int myslot = -1;
+       unsigned long val;
+
+       if (nr == 0) {
+               sys->mem_offset = 0;
+               ret = pci_versatile_setup_resources(sys->resource);
+               if (ret < 0) {
+                       printk("pci_versatile_setup: resources... oops?\n");
+                       goto out;
+               }
+       } else {
+               printk("pci_versatile_setup: resources... nr == 0??\n");
+               goto out;
+       }
+
+       __raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0);
+       __raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1);
+       __raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2);
+
+       __raw_writel(1, SYS_PCICTL);
+
+       val = __raw_readl(SYS_PCICTL);
+       if (!(val & 1)) {
+               printk("Not plugged into PCI backplane!\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       /*
+        *  We need to discover the PCI core first to configure itself
+        *  before the main PCI probing is performed
+        */
+       for (i=0; i<32; i++) {
+               if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) &&
+                   (__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) {
+                       myslot = i;
+
+                       __raw_writel(myslot, PCI_SELFID);
+                       val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+                       val |= (1<<2);
+                       __raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+                       break;
+               }
+       }
+
+       if (myslot == -1) {
+               printk("Cannot find PCI core!\n");
+               ret = -EIO;
+       } else {
+               printk("PCI core found (slot %d)\n",myslot);
+               /* Do not to map Versatile FPGA PCI device
+                  into memory space as we are short of
+                  mappable memory */
+               pci_slot_ignore |= (1 << myslot);
+               ret = 1;
+       }
+
+ out:
+       return ret;
+}
+
+
+struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
+{
+       return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys);
+}
+
+/*
+ * V3_LB_BASE? - local bus address
+ * V3_LB_MAP?  - pci bus address
+ */
+void __init pci_versatile_preinit(void)
+{
+}
+
+void __init pci_versatile_postinit(void)
+{
+}
+
+
+/*
+ * map the specified device/slot/pin to an IRQ.   Different backplanes may need to modify this.
+ */
+static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq;
+       int devslot = PCI_SLOT(dev->devfn);
+
+       /* slot,  pin,  irq
+           24    1     27
+           25    1     28      untested
+           26    1     29
+           27    1     30      untested
+       */
+
+       irq = 27 + ((slot + pin + 2) % 3);      /* Fudged */
+
+       printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
+
+       return irq;
+}
+
+static struct hw_pci versatile_pci __initdata = {
+       .swizzle                = NULL,
+       .map_irq                = versatile_map_irq,
+       .nr_controllers         = 1,
+       .setup                  = pci_versatile_setup,
+       .scan                   = pci_versatile_scan_bus,
+       .preinit                = pci_versatile_preinit,
+       .postinit               = pci_versatile_postinit,
+};
+
+static int __init versatile_pci_init(void)
+{
+       pci_common_init(&versatile_pci);
+       return 0;
+}
+
+subsys_initcall(versatile_pci_init);
index 3fefb43c67f7c8cc851285e83e21d3648902027a..95606b4a3ba67942ae16563a21c783d35cc9753b 100644 (file)
@@ -62,7 +62,7 @@ config CPU_ARM720T
 # ARM920T
 config CPU_ARM920T
        bool "Support ARM920T processor" if !ARCH_S3C2410
-       depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
+       depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
        default y if ARCH_S3C2410
        select CPU_32v4
        select CPU_ABRT_EV4T
index a8c00236bd3d54283da26f1fe36d3a0cc3d6c636..27d041574ea7891ab91bd9c1917ba1ee7e2be58f 100644 (file)
@@ -30,8 +30,6 @@
 
 static DEFINE_SPINLOCK(v6_lock);
 
-#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
-
 /*
  * Copy the user page.  No aliasing to deal with so we can just
  * attack the kernel's existing mapping of these pages.
@@ -55,7 +53,7 @@ void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
  */
 void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
-       unsigned int offset = DCACHE_COLOUR(vaddr);
+       unsigned int offset = CACHE_COLOUR(vaddr);
        unsigned long from, to;
 
        /*
@@ -95,7 +93,7 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
  */
 void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
 {
-       unsigned int offset = DCACHE_COLOUR(vaddr);
+       unsigned int offset = CACHE_COLOUR(vaddr);
        unsigned long to = to_address + (offset << PAGE_SHIFT);
 
        /*
index 01967ddeef53df2cb72bda5d600419e63c392f82..be4ab3d73c91965448f064448136f7c078d9fb30 100644 (file)
@@ -77,9 +77,8 @@ no_pmd:
 }
 
 static void
-make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
+make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 {
-       struct address_space *mapping = page_mapping(page);
        struct mm_struct *mm = vma->vm_mm;
        struct vm_area_struct *mpnt;
        struct prio_tree_iter iter;
@@ -87,9 +86,6 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
        pgoff_t pgoff;
        int aliases = 0;
 
-       if (!mapping)
-               return;
-
        pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
 
        /*
@@ -115,9 +111,11 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
        if (aliases)
                adjust_pte(vma, addr);
        else
-               flush_cache_page(vma, addr, page_to_pfn(page));
+               flush_cache_page(vma, addr, pfn);
 }
 
+void __flush_dcache_page(struct address_space *mapping, struct page *page);
+
 /*
  * Take care of architecture specific things when placing a new PTE into
  * a page table, or changing an existing PTE.  Basically, there are two
@@ -134,29 +132,22 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 {
        unsigned long pfn = pte_pfn(pte);
+       struct address_space *mapping;
        struct page *page;
 
        if (!pfn_valid(pfn))
                return;
+
        page = pfn_to_page(pfn);
-       if (page_mapping(page)) {
+       mapping = page_mapping(page);
+       if (mapping) {
                int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
 
-               if (dirty) {
-                       /*
-                        * This is our first userspace mapping of this page.
-                        * Ensure that the physical page is coherent with
-                        * the kernel mapping.
-                        *
-                        * FIXME: only need to do this on VIVT and aliasing
-                        *        VIPT cache architectures.  We can do that
-                        *        by choosing whether to set this bit...
-                        */
-                       __cpuc_flush_dcache_page(page_address(page));
-               }
+               if (dirty)
+                       __flush_dcache_page(mapping, page);
 
                if (cache_is_vivt())
-                       make_coherent(vma, addr, page, dirty);
+                       make_coherent(mapping, vma, addr, pfn);
        }
 }
 
index 4085ed983e46e07c3ac62ba31f8b0e605ee2594c..191788fb18d13a4f3adad73afd92a649c0c7ff21 100644 (file)
@@ -37,13 +37,8 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
 #define flush_pfn_alias(pfn,vaddr)     do { } while (0)
 #endif
 
-static void __flush_dcache_page(struct address_space *mapping, struct page *page)
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
 {
-       struct mm_struct *mm = current->active_mm;
-       struct vm_area_struct *mpnt;
-       struct prio_tree_iter iter;
-       pgoff_t pgoff;
-
        /*
         * Writeback any data associated with the kernel mapping of this
         * page.  This ensures that data in the physical page is mutually
@@ -52,24 +47,21 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
        __cpuc_flush_dcache_page(page_address(page));
 
        /*
-        * If there's no mapping pointer here, then this page isn't
-        * visible to userspace yet, so there are no cache lines
-        * associated with any other aliases.
-        */
-       if (!mapping)
-               return;
-
-       /*
-        * This is a page cache page.  If we have a VIPT cache, we
-        * only need to do one flush - which would be at the relevant
+        * If this is a page cache page, and we have an aliasing VIPT cache,
+        * we only need to do one flush - which would be at the relevant
         * userspace colour, which is congruent with page->index.
         */
-       if (cache_is_vipt()) {
-               if (cache_is_vipt_aliasing())
-                       flush_pfn_alias(page_to_pfn(page),
-                                       page->index << PAGE_CACHE_SHIFT);
-               return;
-       }
+       if (mapping && cache_is_vipt_aliasing())
+               flush_pfn_alias(page_to_pfn(page),
+                               page->index << PAGE_CACHE_SHIFT);
+}
+
+static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
+{
+       struct mm_struct *mm = current->active_mm;
+       struct vm_area_struct *mpnt;
+       struct prio_tree_iter iter;
+       pgoff_t pgoff;
 
        /*
         * There are possible user space mappings of this page:
@@ -116,12 +108,12 @@ void flush_dcache_page(struct page *page)
 {
        struct address_space *mapping = page_mapping(page);
 
-       if (cache_is_vipt_nonaliasing())
-               return;
-
        if (mapping && !mapping_mapped(mapping))
                set_bit(PG_dcache_dirty, &page->flags);
-       else
+       else {
                __flush_dcache_page(mapping, page);
+               if (mapping && cache_is_vivt())
+                       __flush_dcache_aliases(mapping, page);
+       }
 }
 EXPORT_SYMBOL(flush_dcache_page);
index 00bb8fd37a59f1bcfdb92c0f60bb314c9b710f8a..7110e54182b1e146ce6d26254965436cb971d6d4 100644 (file)
@@ -170,3 +170,50 @@ void __iounmap(void __iomem *addr)
        vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
 EXPORT_SYMBOL(__iounmap);
+
+#ifdef __io
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       return __io(port);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif
+
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len   = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM) {
+               if (flags & IORESOURCE_CACHEABLE)
+                       return ioremap(start, len);
+               return ioremap_nocache(start, len);
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+       if ((unsigned long)addr >= VMALLOC_START &&
+           (unsigned long)addr < VMALLOC_END)
+               iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+#endif
index 344164681d2ce5a4f4373ed9637140e42d17fcee..8316426ccaf60036c59d3cd45e18835d8e19c88a 100644 (file)
@@ -423,6 +423,9 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
        tbl->it_largehint = tbl->it_halfpoint;
        spin_lock_init(&tbl->it_lock);
 
+       /* Clear the hardware table in case firmware left allocations in it */
+       ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
+
        if (!welcomed) {
                printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
                       novmerge ? "disabled" : "enabled");
index fbad349ec58c2179fce3731d9ead5b8739cbc8c8..4203bd020c828364a42279ea48ef9ac1c85f6f03 100644 (file)
@@ -375,7 +375,7 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
         * cpus are assumed to be secondary threads.
         */
        if (system_state < SYSTEM_RUNNING &&
-           cur_cpu_spec->cpu_features & CPU_FTR_SMT &&
+           cpu_has_feature(CPU_FTR_SMT) &&
            !smt_enabled_at_boot && nr % 2 != 0)
                return 0;
 
@@ -419,8 +419,8 @@ void __init smp_init_pSeries(void)
 #endif
 
        /* Mark threads which are still spinning in hold loops. */
-       if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-               for_each_present_cpu(i) {
+       if (cpu_has_feature(CPU_FTR_SMT)) {
+               for_each_present_cpu(i) { 
                        if (i % 2 == 0)
                                /*
                                 * Even-numbered logical cpus correspond to
@@ -428,8 +428,9 @@ void __init smp_init_pSeries(void)
                                 */
                                cpu_set(i, of_spin_map);
                }
-       else
+       } else {
                of_spin_map = cpu_present_map;
+       }
 
        cpu_clear(boot_cpuid, of_spin_map);
 
index ff65dc33320ee779bf89b4b602d64da4d22a003b..b0c3b829fe47c43eac16b7d5ff9d885f0fd1b5c4 100644 (file)
@@ -440,7 +440,7 @@ static int rtasd(void *unused)
                goto error;
        }
 
-       printk(KERN_ERR "RTAS daemon started\n");
+       printk(KERN_INFO "RTAS daemon started\n");
 
        DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
 
@@ -485,7 +485,7 @@ static int __init rtas_init(void)
        /* No RTAS, only warn if we are on a pSeries box  */
        if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
                if (systemcfg->platform & PLATFORM_PSERIES)
-                       printk(KERN_ERR "rtasd: no event-scan on system\n");
+                       printk(KERN_INFO "rtasd: no event-scan on system\n");
                return 1;
        }
 
index ab659d37b4d2bb4aa0dc50e932c512adea781e59..4e98c215e5b1bd63788ff031638191e0024045e8 100644 (file)
@@ -192,7 +192,12 @@ static struct miscdevice ixp2000_wdt_miscdev =
 
 static int __init ixp2000_wdt_init(void)
 {
-       wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;;
+       if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+               printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
+               return -EIO;
+       }
+
+       wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
 
        return misc_register(&ixp2000_wdt_miscdev);
 }
index fbd9ff79b7b8cb98bdfa5b788033909e84b5b399..e3c95882353341bb103a3d9164bd12d2e3fb2d58 100644 (file)
@@ -765,8 +765,6 @@ void fcp_release(fc_channel *fcchain, int count)  /* count must > 0 */
 
 static void fcp_scsi_done (Scsi_Cmnd *SCpnt)
 {
-       unsigned long flags;
-
        if (FCP_CMND(SCpnt)->done)
                FCP_CMND(SCpnt)->done(SCpnt);
 }
@@ -907,8 +905,6 @@ int fcp_scsi_abort(Scsi_Cmnd *SCpnt)
         */
 
        if (++fc->abort_count < (fc->can_queue >> 1)) {
-               unsigned long flags;
-
                SCpnt->result = DID_ABORT;
                fcmd->done(SCpnt);
                printk("FC: soft abort\n");
@@ -931,6 +927,7 @@ void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt)
 
 int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
 {
+       unsigned long flags;
        fcp_cmd *cmd;
        fcp_cmnd *fcmd;
        fc_channel *fc = FC_SCMND(SCpnt);
@@ -1028,6 +1025,7 @@ static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
 
 int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
 {
+       unsigned long flags;
        int rc;
 
        spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
index c4eaaad2c69bedd3f67004aae7960802709739f6..5f526dd0aaa1e1b2b8450109e9962ea6ead776da 100644 (file)
@@ -941,7 +941,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
         */
        cmd->scsi_done = scsi_done;
 
-       ahd_lock(ahd, &flags);
+       ahd_midlayer_entrypoint_lock(ahd, &flags);
 
        /*
         * Close the race of a command that was in the process of
@@ -955,7 +955,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
                ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
                ahd_linux_queue_cmd_complete(ahd, cmd);
                ahd_schedule_completeq(ahd);
-               ahd_unlock(ahd, &flags);
+               ahd_midlayer_entrypoint_unlock(ahd, &flags);
                return (0);
        }
        dev = ahd_linux_get_device(ahd, cmd->device->channel,
@@ -965,7 +965,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
                ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
                ahd_linux_queue_cmd_complete(ahd, cmd);
                ahd_schedule_completeq(ahd);
-               ahd_unlock(ahd, &flags);
+               ahd_midlayer_entrypoint_unlock(ahd, &flags);
                printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
                       ahd_name(ahd));
                return (0);
@@ -979,7 +979,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
                dev->flags |= AHD_DEV_ON_RUN_LIST;
                ahd_linux_run_device_queues(ahd);
        }
-       ahd_unlock(ahd, &flags);
+       ahd_midlayer_entrypoint_unlock(ahd, &flags);
        return (0);
 }
 
diff --git a/include/asm-arm/arch-aaec2000/aaec2000.h b/include/asm-arm/arch-aaec2000/aaec2000.h
new file mode 100644 (file)
index 0000000..0e9b7e1
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/aaec2000.h
+ *
+ *  AAEC-2000 registers definition
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_AAEC2000_H
+#define __ASM_ARCH_AAEC2000_H
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error You must include hardware.h not this file
+#endif /* __ASM_ARCH_HARDWARE_H */
+
+/* Interrupt controller */
+#define IRQ_BASE       __REG(0x80000500)
+#define IRQ_INTSR      __REG(0x80000500)       /* Int Status Register */
+#define IRQ_INTRSR     __REG(0x80000504)       /* Int Raw (unmasked) Status */
+#define IRQ_INTENS     __REG(0x80000508)       /* Int Enable Set */
+#define IRQ_INTENC     __REG(0x8000050c)       /* Int Enable Clear */
+
+/* UART 1 */
+#define UART1_BASE     __REG(0x80000600)
+#define UART1_DR       __REG(0x80000600) /* Data/FIFO Register */
+#define UART1_LCR      __REG(0x80000604) /* Link Control Register */
+#define UART1_BRCR     __REG(0x80000608) /* Baud Rate Control Register */
+#define UART1_CR       __REG(0x8000060c) /* Control Register */
+#define UART1_SR       __REG(0x80000610) /* Status Register */
+#define UART1_INT      __REG(0x80000614) /* Interrupt Status Register */
+#define UART1_INTM     __REG(0x80000618) /* Interrupt Mask Register */
+#define UART1_INTRES   __REG(0x8000061c) /* Int Result (masked status) Register */
+
+/* UART 2 */
+#define UART2_BASE     __REG(0x80000700)
+#define UART2_DR       __REG(0x80000700) /* Data/FIFO Register */
+#define UART2_LCR      __REG(0x80000704) /* Link Control Register */
+#define UART2_BRCR     __REG(0x80000708) /* Baud Rate Control Register */
+#define UART2_CR       __REG(0x8000070c) /* Control Register */
+#define UART2_SR       __REG(0x80000710) /* Status Register */
+#define UART2_INT      __REG(0x80000714) /* Interrupt Status Register */
+#define UART2_INTM     __REG(0x80000718) /* Interrupt Mask Register */
+#define UART2_INTRES   __REG(0x8000071c) /* Int Result (masked status) Register */
+
+/* UART 3 */
+#define UART3_BASE     __REG(0x80000800)
+#define UART3_DR       __REG(0x80000800) /* Data/FIFO Register */
+#define UART3_LCR      __REG(0x80000804) /* Link Control Register */
+#define UART3_BRCR     __REG(0x80000808) /* Baud Rate Control Register */
+#define UART3_CR       __REG(0x8000080c) /* Control Register */
+#define UART3_SR       __REG(0x80000810) /* Status Register */
+#define UART3_INT      __REG(0x80000814) /* Interrupt Status Register */
+#define UART3_INTM     __REG(0x80000818) /* Interrupt Mask Register */
+#define UART3_INTRES   __REG(0x8000081c) /* Int Result (masked status) Register */
+
+/* These are used in some places */
+#define _UART1_BASE __PREG(UART1_BASE)
+#define _UART2_BASE __PREG(UART2_BASE)
+#define _UART3_BASE __PREG(UART3_BASE)
+
+/* UART Registers Offsets */
+#define UART_DR                0x00
+#define UART_LCR       0x04
+#define UART_BRCR      0x08
+#define UART_CR                0x0c
+#define UART_SR                0x10
+#define UART_INT       0x14
+#define UART_INTM      0x18
+#define UART_INTRES    0x1c
+
+/* UART_LCR Bitmask */
+#define UART_LCR_BRK   (1 << 0) /* Send Break */
+#define UART_LCR_PEN   (1 << 1) /* Parity Enable */
+#define UART_LCR_EP    (1 << 2) /* Even/Odd Parity */
+#define UART_LCR_S2    (1 << 3) /* One/Two Stop bits */
+#define UART_LCR_FIFO  (1 << 4) /* FIFO Enable */
+#define UART_LCR_WL5   (0 << 5) /* Word Length - 5 bits */
+#define UART_LCR_WL6   (1 << 5) /* Word Length - 6 bits */
+#define UART_LCR_WL7   (1 << 6) /* Word Length - 7 bits */
+#define UART_LCR_WL8   (1 << 7) /* Word Length - 8 bits */
+
+/* UART_CR Bitmask */
+#define UART_CR_EN     (1 << 0) /* UART Enable */
+#define UART_CR_SIR    (1 << 1) /* IrDA SIR Enable */
+#define UART_CR_SIRLP  (1 << 2) /* Low Power IrDA Enable */
+#define UART_CR_RXP    (1 << 3) /* Receive Pin Polarity */
+#define UART_CR_TXP    (1 << 4) /* Transmit Pin Polarity */
+#define UART_CR_MXP    (1 << 5) /* Modem Pin Polarity */
+#define UART_CR_LOOP   (1 << 6) /* Loopback Mode */
+
+/* UART_SR Bitmask */
+#define UART_SR_CTS    (1 << 0) /* Clear To Send Status */
+#define UART_SR_DSR    (1 << 1) /* Data Set Ready Status */
+#define UART_SR_DCD    (1 << 2) /* Data Carrier Detect Status */
+#define UART_SR_TxBSY  (1 << 3) /* Transmitter Busy Status */
+#define UART_SR_RxFE   (1 << 4) /* Receive FIFO Empty Status */
+#define UART_SR_TxFF   (1 << 5) /* Transmit FIFO Full Status */
+#define UART_SR_RxFF   (1 << 6) /* Receive FIFO Full Status */
+#define UART_SR_TxFE   (1 << 7) /* Transmit FIFO Empty Status */
+
+/* UART_INT Bitmask */
+#define UART_INT_RIS   (1 << 0) /* Rx Interrupt */
+#define UART_INT_TIS   (1 << 1) /* Tx Interrupt */
+#define UART_INT_MIS   (1 << 2) /* Modem Interrupt */
+#define UART_INT_RTIS  (1 << 3) /* Receive Timeout Interrupt */
+
+/* Timer 1 */
+#define TIMER1_BASE    __REG(0x80000c00)
+#define TIMER1_LOAD    __REG(0x80000c00)       /* Timer 1 Load Register */
+#define TIMER1_VAL     __REG(0x80000c04)       /* Timer 1 Value Register */
+#define TIMER1_CTRL    __REG(0x80000c08)       /* Timer 1 Control Register */
+#define TIMER1_CLEAR   __REG(0x80000c0c)       /* Timer 1 Clear Register */
+
+/* Timer 2 */
+#define TIMER2_BASE    __REG(0x80000d00)
+#define TIMER2_LOAD    __REG(0x80000d00)       /* Timer 2 Load Register */
+#define TIMER2_VAL     __REG(0x80000d04)       /* Timer 2 Value Register */
+#define TIMER2_CTRL    __REG(0x80000d08)       /* Timer 2 Control Register */
+#define TIMER2_CLEAR   __REG(0x80000d0c)       /* Timer 2 Clear Register */
+
+/* Timer 3 */
+#define TIMER3_BASE    __REG(0x80000e00)
+#define TIMER3_LOAD    __REG(0x80000e00)       /* Timer 3 Load Register */
+#define TIMER3_VAL     __REG(0x80000e04)       /* Timer 3 Value Register */
+#define TIMER3_CTRL    __REG(0x80000e08)       /* Timer 3 Control Register */
+#define TIMER3_CLEAR   __REG(0x80000e0c)       /* Timer 3 Clear Register */
+
+/* Timer Control register bits */
+#define TIMER_CTRL_ENABLE      (1 << 7) /* Enable (Start° Timer */
+#define TIMER_CTRL_PERIODIC    (1 << 6) /* Periodic Running Mode */
+#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
+#define TIMER_CTRL_CLKSEL_508K (1 << 3) /* 508KHz Clock select (Timer 1, 2) */
+#define TIMER_CTRL_CLKSEL_2K   (0 << 3) /* 2KHz Clock Select (Timer 1, 2)*/
+
+/* Power and State Control */
+#define POWER_BASE     __REG(0x80000400)
+#define POWER_PWRSR    __REG(0x80000400) /* Power Status Register */
+#define POWER_PWRCNT   __REG(0x80000404) /* Power/Clock control */
+#define POWER_HALT     __REG(0x80000408) /* Power Idle Mode */
+#define POWER_STDBY    __REG(0x8000040c) /* Power Standby Mode */
+#define POWER_BLEOI    __REG(0x80000410) /* Battery Low End of Interrupt */
+#define POWER_MCEOI    __REG(0x80000414) /* Media Changed EoI */
+#define POWER_TEOI     __REG(0x80000418) /* Tick EoI */
+#define POWER_STFCLR   __REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
+#define POWER_CLKSET   __REG(0x80000420) /* Clock Speed Control */
+
+#endif /* __ARM_ARCH_AAEC2000_H */
diff --git a/include/asm-arm/arch-aaec2000/debug-macro.S b/include/asm-arm/arch-aaec2000/debug-macro.S
new file mode 100644 (file)
index 0000000..e4f1fa5
--- /dev/null
@@ -0,0 +1,36 @@
+/*  linux/include/asm-arm/arch-aaec2000/debug-macro.S
+ *
+ *  Debugging macro include header
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+               .macro  addruart,rx
+               mrc     p15, 0, \rx, c1, c0
+               tst     \rx, #1                 @ MMU enabled?
+               moveq   \rx, #0x80000000                @ physical
+               movne   \rx, #io_p2v(0x80000000)        @ virtual
+               orr     \rx, \rx, #0x00000800
+               .endm
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #0]
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #0x10]
+               tst     \rd, #(1 << 7)
+               beq     1002b
+               .endm
+
+               .macro  waituart,rd,rx
+#if 0
+1001:          ldr     \rd, [\rx, #0x10]
+               tst     \rd, #(1 << 5)
+               beq     1001b
+#endif
+               .endm
diff --git a/include/asm-arm/arch-aaec2000/dma.h b/include/asm-arm/arch-aaec2000/dma.h
new file mode 100644 (file)
index 0000000..28c890b
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/dma.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS         0xffffffff
+#define MAX_DMA_CHANNELS        0
+
+#endif
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
new file mode 100644 (file)
index 0000000..df31313
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/entry-macro.S
+ *
+ *  Low-level IRQ helper for aaec-2000 based platforms
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+               mov     r4, #0xf8000000
+               add     r4, r4, #0x00000500
+               mov     \base, r4
+               ldr     \irqstat, [\base, #0]
+               cmp     \irqstat, #0
+               bne     1001f
+               ldr     \irqnr, =NR_IRQS+1
+               b       1003f
+1001:          mov     \irqnr, #0
+1002:          ands    \tmp, \irqstat, #1
+               mov     \irqstat, \irqstat, LSR #1
+               add     \irqnr, \irqnr, #1
+               beq     1002b
+               sub     \irqnr, \irqnr, #1
+1003:
+               .endm
diff --git a/include/asm-arm/arch-aaec2000/hardware.h b/include/asm-arm/arch-aaec2000/hardware.h
new file mode 100644 (file)
index 0000000..4c37219
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/hardware.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+
+/* The kernel is loaded at physical address 0xf8000000.
+ * We map the IO space a bit after
+ */
+#define PIO_APB_BASE   0x80000000
+#define VIO_APB_BASE   0xf8000000
+#define IO_APB_LENGTH  0x2000
+#define PIO_AHB_BASE   0x80002000
+#define VIO_AHB_BASE   0xf8002000
+#define IO_AHB_LENGTH  0x2000
+
+#define VIO_BASE    VIO_APB_BASE
+#define PIO_BASE    PIO_APB_BASE
+
+#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
+#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
+
+#ifndef __ASSEMBLY__
+
+#include <asm/types.h>
+
+/* FIXME: Is it needed to optimize this a la pxa ?? */
+#define __REG(x)    (*((volatile u32 *)io_p2v(x)))
+#define __PREG(x)   (io_v2p((u32)&(x)))
+
+#else /* __ASSEMBLY__ */
+
+#define __REG(x)    io_p2v(x)
+#define __PREG(x)   io_v2p(x)
+
+#endif
+
+#include "aaec2000.h"
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-aaec2000/io.h b/include/asm-arm/arch-aaec2000/io.h
new file mode 100644 (file)
index 0000000..c58a8d1
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/io.h
+ *
+ *  Copied from asm/arch/sa1100/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)                        ((void __iomem *)(a))
+#define __mem_pci(a)           (a)
+#define __mem_isa(a)           (a)
+
+#endif
diff --git a/include/asm-arm/arch-aaec2000/irqs.h b/include/asm-arm/arch-aaec2000/irqs.h
new file mode 100644 (file)
index 0000000..de25222
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/irqs.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+
+#define INT_GPIOF0_FIQ 0  /* External GPIO Port F O Fast Interrupt Input */
+#define INT_BL_FIQ     1  /* Battery Low Fast Interrupt */
+#define INT_WE_FIQ     2  /* Watchdog Expired Fast Interrupt */
+#define INT_MV_FIQ     3  /* Media Changed Interrupt */
+#define INT_SC         4  /* Sound Codec Interrupt */
+#define INT_GPIO1      5  /* GPIO Port F Configurable Int 1 */
+#define INT_GPIO2      6  /* GPIO Port F Configurable Int 2 */
+#define INT_GPIO3      7  /* GPIO Port F Configurable Int 3 */
+#define INT_TMR1_OFL   8  /* Timer 1 Overflow Interrupt */
+#define INT_TMR2_OFL   9  /* Timer 2 Overflow Interrupt */
+#define INT_RTC_CM     10 /* RTC Compare Match Interrupt */
+#define INT_TICK       11 /* 64Hz Tick Interrupt */
+#define INT_UART1      12 /* UART1 Interrupt */
+#define INT_UART2      13 /* UART2 & Modem State Changed Interrupt */
+#define INT_LCD                14 /* LCD Interrupt */
+#define INT_SSI                15 /* SSI End of Transfer Interrupt */
+#define INT_UART3      16 /* UART3 Interrupt */
+#define INT_SCI                17 /* SCI Interrupt */
+#define INT_AAC                18 /* Advanced Audio Codec Interrupt */
+#define INT_MMC                19 /* MMC Interrupt */
+#define INT_USB                20 /* USB Interrupt */
+#define INT_DMA                21 /* DMA Interrupt */
+#define INT_TMR3_UOFL  22 /* Timer 3 Underflow Interrupt */
+#define INT_GPIO4      23 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO5      24 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO6      25 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO7      26 /* GPIO Port F Configurable Int 4 */
+#define INT_BMI                27 /* BMI Interrupt */
+
+#define NR_IRQS                (INT_BMI + 1)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
new file mode 100644 (file)
index 0000000..681b6a6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/memory.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <linux/config.h>
+
+#define PHYS_OFFSET    (0xf0000000UL)
+
+#define __virt_to_bus(x)       __virt_to_phys(x)
+#define __bus_to_virt(x)       __phys_to_virt(x)
+
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * The nodes are the followings:
+ *
+ *   node 0: 0xf000.0000 - 0xf3ff.ffff
+ *   node 1: 0xf400.0000 - 0xf7ff.ffff
+ *   node 2: 0xf800.0000 - 0xfbff.ffff
+ *   node 3: 0xfc00.0000 - 0xffff.ffff
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) \
+       (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn) \
+       (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr)  NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
+
+/*
+ * Given a page frame number, find the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define PFN_TO_MAPBASE(pfn)     NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+/*
+ *  Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
+ *  and returns the index corresponding to the appropriate page in the
+ *  node's mem_map.
+ */
+#define LOCAL_MAP_NR(addr) \
+        (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
+
+#define NODE_MAX_MEM_SHIFT     26
+#define NODE_MAX_MEM_SIZE      (1 << NODE_MAX_MEM_SHIFT)
+
+#else
+
+#define PFN_TO_NID(addr)       (0)
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/include/asm-arm/arch-aaec2000/param.h b/include/asm-arm/arch-aaec2000/param.h
new file mode 100644 (file)
index 0000000..139936c
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/param.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+#endif /* __ASM_ARCH_PARAM_H */
+
diff --git a/include/asm-arm/arch-aaec2000/system.h b/include/asm-arm/arch-aaec2000/system.h
new file mode 100644 (file)
index 0000000..08de97b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  linux/include/asm-arm/arch-aaed2000/system.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       cpu_reset(0);
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-aaec2000/timex.h b/include/asm-arm/arch-aaec2000/timex.h
new file mode 100644 (file)
index 0000000..f5708b3
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/timex.h
+ *
+ *  AAEC-2000 Architecture timex specification
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#define CLOCK_TICK_RATE                508000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/include/asm-arm/arch-aaec2000/uncompress.h b/include/asm-arm/arch-aaec2000/uncompress.h
new file mode 100644 (file)
index 0000000..fff0c94
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/uncompress.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include "hardware.h"
+
+#define UART(x)         (*(volatile unsigned long *)(serial_port + (x)))
+
+static void putstr( const char *s )
+{
+       unsigned long serial_port;
+        do {
+               serial_port = _UART3_BASE;
+               if (UART(UART_CR) & UART_CR_EN) break;
+               serial_port = _UART1_BASE;
+               if (UART(UART_CR) & UART_CR_EN) break;
+               serial_port = _UART2_BASE;
+               if (UART(UART_CR) & UART_CR_EN) break;
+               return;
+       } while (0);
+
+       for (; *s; s++) {
+               /* wait for space in the UART's transmitter */
+               while ((UART(UART_SR) & UART_SR_TxFF));
+               /* send the character out. */
+               UART(UART_DR) = *s;
+               /* if a LF, also do CR... */
+               if (*s == 10) {
+                       while ((UART(UART_SR) & UART_SR_TxFF));
+                       UART(UART_DR) = 13;
+               }
+       }
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/arch-aaec2000/vmalloc.h b/include/asm-arm/arch-aaec2000/vmalloc.h
new file mode 100644 (file)
index 0000000..ecb991e
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/vmalloc.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END            (PAGE_OFFSET + 0x10000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
index 6c56708d0ff0c98a4e484330a447c30b6ad76524..a1d9e181b10f1c1d579cf4b3fa4d30db1a39b9a5 100644 (file)
 #define IXP2000_MIN_REV_MASK           0x0000000F
 #define IXP2000_PROD_ID_MASK           0xFFFFFFFF
 
+#define IXP2000_PRODUCT_ID             GLOBAL_REG(0x00)
 #define IXP2000_MISC_CONTROL           GLOBAL_REG(0x04)
 #define IXP2000_MSF_CLK_CNTRL                  GLOBAL_REG(0x08)
 #define IXP2000_RESET0                 GLOBAL_REG(0x0c)
index d5fb4a251e7f783507982b96795dad09ebde33d8..41c1bee342ad0ba04c5a4644a2e2c291c79ff78d 100644 (file)
 #include <asm/sizes.h>
 #include <asm/arch/platform.h>
 
-// FIXME = PCI settings need to be fixed!!!!!
-
 /*
- * Similar to above, but for PCI addresses (memory, IO, Config and the
- * V3 chip itself).  WARNING: this has to mirror definitions in platform.h
+ * PCI space virtual addresses
  */
-#define PCI_MEMORY_VADDR       0xe8000000
-#define PCI_CONFIG_VADDR       0xec000000
-#define PCI_V3_VADDR           0xed000000
-#define PCI_IO_VADDR           0xee000000
+#define VERSATILE_PCI_VIRT_BASE                0xe8000000
+#define VERSATILE_PCI_CFG_VIRT_BASE    0xe9000000
+
+#if 0
+#define VERSATILE_PCI_VIRT_MEM_BASE0   0xf4000000
+#define VERSATILE_PCI_VIRT_MEM_BASE1   0xf5000000
+#define VERSATILE_PCI_VIRT_MEM_BASE2   0xf6000000
+
+#define PCIO_BASE                      VERSATILE_PCI_VIRT_MEM_BASE0
+#define PCIMEM_BASE                    VERSATILE_PCI_VIRT_MEM_BASE1
+#endif
+
+/* CIK guesswork */
+#define PCIBIOS_MIN_IO                 0x44000000
+#define PCIBIOS_MIN_MEM                        0x50000000
 
-#define PCIO_BASE              PCI_IO_VADDR
-#define PCIMEM_BASE            PCI_MEMORY_VADDR
+#define pcibios_assign_all_busses()     1
 
 /* macro to get at IO space when running virtually */
 #define IO_ADDRESS(x)          (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
index dbb7158788fc99758c35914a59a7868fb01222c6..9f895bf61494308a2c2add721009c3699125781d 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
+#define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(a)                        ((void __iomem *)(a))
 #define __mem_pci(a)           (a)
index a71093e44c58b0c0854ee381ff8dae8d7d358902..cbdd9fb963320166473a3f2da845410d57cc6c56 100644 (file)
@@ -76,7 +76,7 @@
 #define VERSATILE_SYS_NVFLAGSSET_OFFSET       0x38
 #define VERSATILE_SYS_NVFLAGSCLR_OFFSET       0x3C
 #define VERSATILE_SYS_RESETCTL_OFFSET         0x40
-#define VERSATILE_SYS_PICCTL_OFFSET           0x44
+#define VERSATILE_SYS_PCICTL_OFFSET           0x44
 #define VERSATILE_SYS_MCI_OFFSET              0x48
 #define VERSATILE_SYS_FLASH_OFFSET            0x4C
 #define VERSATILE_SYS_CLCD_OFFSET             0x50
 #define VERSATILE_SYS_NVFLAGSSET              (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET)
 #define VERSATILE_SYS_NVFLAGSCLR              (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET)
 #define VERSATILE_SYS_RESETCTL                (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET)
-#define VERSATILE_SYS_PICCTL                  (VERSATILE_SYS_BASE + VERSATILE_SYS_PICCTL_OFFSET)
+#define VERSATILE_SYS_PCICTL                  (VERSATILE_SYS_BASE + VERSATILE_SYS_PCICTL_OFFSET)
 #define VERSATILE_SYS_MCI                     (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET)
 #define VERSATILE_SYS_FLASH                   (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET)
 #define VERSATILE_SYS_CLCD                    (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET)
 #define VERSATILE_SSMC_BASE            0x20000000      /* SSMC */
 #define VERSATILE_IB2_BASE             0x24000000      /* IB2 module */
 #define VERSATILE_MBX_BASE             0x40000000      /* MBX */
+
+/* PCI space */
 #define VERSATILE_PCI_BASE             0x41000000      /* PCI Interface */
+#define VERSATILE_PCI_CFG_BASE        0x42000000
+#define VERSATILE_PCI_MEM_BASE0        0x44000000
+#define VERSATILE_PCI_MEM_BASE1        0x50000000
+#define VERSATILE_PCI_MEM_BASE2        0x60000000
+/* Sizes of above maps */
+#define VERSATILE_PCI_BASE_SIZE               0x01000000
+#define VERSATILE_PCI_CFG_BASE_SIZE    0x02000000
+#define VERSATILE_PCI_MEM_BASE0_SIZE   0x0c000000      /* 32Mb */
+#define VERSATILE_PCI_MEM_BASE1_SIZE   0x10000000      /* 256Mb */
+#define VERSATILE_PCI_MEM_BASE2_SIZE   0x10000000      /* 256Mb */
+
 #define VERSATILE_SDRAM67_BASE         0x70000000      /* SDRAM banks 6 and 7 */
 #define VERSATILE_LT_BASE              0x80000000      /* Logic Tile expansion */
 
index 09ffeed507c2098a980b1f7eb65e5369d0598907..035cdcff43d233e8566e5ed0ce3e6b04514be4d9 100644 (file)
@@ -16,6 +16,9 @@
 
 #include <asm/mman.h>
 #include <asm/glue.h>
+#include <asm/shmparam.h>
+
+#define CACHE_COLOUR(vaddr)    ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
 /*
  *     Cache Model
index 658ffa384fdab980edae60e9a48df8bfd8979b96..08a46302d26556053e4cdbce8bcc60a164a51011 100644 (file)
@@ -272,6 +272,33 @@ extern void __iounmap(void __iomem *addr);
 #define iounmap(cookie)                        __arch_iounmap(cookie)
 #endif
 
+/*
+ * io{read,write}{8,16,32} macros
+ */
+#define ioread8(p)     ({ unsigned int __v = __raw_readb(p); __v; })
+#define ioread16(p)    ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })
+#define ioread32(p)    ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })
+
+#define iowrite8(v,p)  __raw_writeb(v, p)
+#define iowrite16(v,p) __raw_writew(cpu_to_le16(v), p)
+#define iowrite32(v,p) __raw_writel(cpu_to_le32(v), p)
+
+#define ioread8_rep(p,d,c)     __raw_readsb(p,d,c)
+#define ioread16_rep(p,d,c)    __raw_readsw(p,d,c)
+#define ioread32_rep(p,d,c)    __raw_readsl(p,d,c)
+
+#define iowrite8_rep(p,s,c)    __raw_writesb(p,s,c)
+#define iowrite16_rep(p,s,c)   __raw_writesw(p,s,c)
+#define iowrite32_rep(p,s,c)   __raw_writesl(p,s,c)
+
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *addr);
+
+struct pci_dev;
+
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
+
 /*
  * can the hardware map this into one segment or not, given no other
  * constraints.
index 31d3fc25ccbd0efd1a4d45b5c2716db8999cd814..09a1451c1159575c2ca94b6c247eb9e0b0a187e0 100644 (file)
@@ -20,7 +20,7 @@
 #define SIOCATALKDIFADDR       (SIOCPROTOPRIVATE + 0)
 
 struct atalk_addr {
-       __u16   s_net;
+       __be16  s_net;
        __u8    s_node;
 };
 
@@ -33,8 +33,8 @@ struct sockaddr_at {
 
 struct atalk_netrange {
        __u8    nr_phase;
-       __u16   nr_firstnet;
-       __u16   nr_lastnet;
+       __be16  nr_firstnet;
+       __be16  nr_lastnet;
 };
 
 #ifdef __KERNEL__
@@ -70,8 +70,8 @@ struct atalk_iface {
 struct atalk_sock {
        /* struct sock has to be the first member of atalk_sock */
        struct sock     sk;
-       unsigned short  dest_net;
-       unsigned short  src_net;
+       __be16          dest_net;
+       __be16          src_net;
        unsigned char   dest_node;
        unsigned char   src_node;
        unsigned char   dest_port;
@@ -95,9 +95,9 @@ struct ddpehdr {
                deh_hops:4,
                deh_len:10;
 #endif
-       __u16   deh_sum;
-       __u16   deh_dnet;
-       __u16   deh_snet;
+       __be16  deh_sum;
+       __be16  deh_dnet;
+       __be16  deh_snet;
        __u8    deh_dnode;
        __u8    deh_snode;
        __u8    deh_dport;
@@ -142,24 +142,24 @@ struct ddpshdr {
 
 /* AppleTalk AARP headers */
 struct elapaarp {
-       __u16   hw_type;
+       __be16  hw_type;
 #define AARP_HW_TYPE_ETHERNET          1
 #define AARP_HW_TYPE_TOKENRING         2
-       __u16   pa_type;
+       __be16  pa_type;
        __u8    hw_len;
        __u8    pa_len;
 #define AARP_PA_ALEN                   4
-       __u16   function;
+       __be16  function;
 #define AARP_REQUEST                   1
 #define AARP_REPLY                     2
 #define AARP_PROBE                     3
        __u8    hw_src[ETH_ALEN]        __attribute__ ((packed));
        __u8    pa_src_zero             __attribute__ ((packed));
-       __u16   pa_src_net              __attribute__ ((packed));
+       __be16  pa_src_net              __attribute__ ((packed));
        __u8    pa_src_node             __attribute__ ((packed));
        __u8    hw_dst[ETH_ALEN]        __attribute__ ((packed));
        __u8    pa_dst_zero             __attribute__ ((packed));
-       __u16   pa_dst_net              __attribute__ ((packed));
+       __be16  pa_dst_net              __attribute__ ((packed));
        __u8    pa_dst_node             __attribute__ ((packed));       
 };
 
index e38407a23d04bd0ac0706fd23774fc502cbda85f..561d4dc7583640cb28cb4fbbaf7a285ad4035da4 100644 (file)
@@ -14,6 +14,7 @@
 #define NETLINK_SELINUX                7       /* SELinux event notifications */
 #define NETLINK_ARPD           8
 #define NETLINK_AUDIT          9       /* auditing */
+#define NETLINK_FIB_LOOKUP     10      
 #define NETLINK_ROUTE6         11      /* af_inet6 route comm channel */
 #define NETLINK_IP6_FW         13
 #define NETLINK_DNRTMSG                14      /* DECnet routing messages */
index e6b5192202453edfc6fd7d1fac27d2d2fb5c2ef2..724066778affe84f50bbdf8d6a08a245e26132f4 100644 (file)
@@ -245,6 +245,7 @@ struct sadb_x_nat_t_port {
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS       1
+#define SADB_SAFLAGS_NOPMTUDISC        0x20000000
 #define SADB_SAFLAGS_DECAP_DSCP        0x40000000
 #define SADB_SAFLAGS_NOECN     0x80000000
 
index d68391a9b9f30c5a1aa01e8e2f3f551ff62491cd..f0d423300d84aead0467e222d4d3d3961627abef 100644 (file)
@@ -196,6 +196,7 @@ struct xfrm_usersa_info {
        __u8                            flags;
 #define XFRM_STATE_NOECN       1
 #define XFRM_STATE_DECAP_DSCP  2
+#define XFRM_STATE_NOPMTUDISC  4
 };
 
 struct xfrm_usersa_id {
index 9e6368a5454760fa9bc1c56fc691b110474094b3..828a3a93dda10e07ce851476894296f5b7e4a68f 100644 (file)
@@ -220,7 +220,7 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25)
        }
 }
 
-static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
        skb->dev      = dev;
        skb->pkt_type = PACKET_HOST;
index e5a5f6b62f8800a537e67540b08c56f1c7e0b656..a4208a336ac09e58061af807e28a417f9ad1dd69 100644 (file)
@@ -109,6 +109,20 @@ struct fib_result {
 #endif
 };
 
+struct fib_result_nl {
+       u32             fl_addr;   /* To be looked up*/ 
+       u32             fl_fwmark; 
+       unsigned char   fl_tos;
+       unsigned char   fl_scope;
+       unsigned char   tb_id_in;
+
+       unsigned char   tb_id;      /* Results */
+       unsigned char   prefixlen;
+       unsigned char   nh_sel;
+       unsigned char   type;
+       unsigned char   scope;
+       int             err;      
+};
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
index ebc5282e6d584dc9dc0551c44b4387e7b1e3eb9a..dc107ffad483f0c1863f77a5a415050435c1dd8d 100644 (file)
@@ -65,9 +65,11 @@ typedef enum {
        SCTP_CMD_TIMER_START,   /* Start a timer.  */
        SCTP_CMD_TIMER_RESTART, /* Restart a timer. */
        SCTP_CMD_TIMER_STOP,    /* Stop a timer. */
-       SCTP_CMD_COUNTER_RESET, /* Reset a counter. */
-       SCTP_CMD_COUNTER_INC,   /* Increment a counter. */
+       SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */
+       SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */
+       SCTP_CMD_INIT_COUNTER_INC,   /* Increment init counter. */
        SCTP_CMD_INIT_RESTART,  /* High level, do init timer work. */
+       SCTP_CMD_COOKIEECHO_RESTART,  /* High level, do cookie-echo timer work. */
        SCTP_CMD_INIT_FAILED,   /* High level, do init failure work. */
        SCTP_CMD_REPORT_DUP,    /* Report a duplicate TSN.  */
        SCTP_CMD_STRIKE,        /* Mark a strike against a transport.  */
@@ -118,7 +120,6 @@ typedef union {
        int error;
        sctp_state_t state;
        sctp_event_timeout_t to;
-       sctp_counter_t counter;
        void *ptr;
        struct sctp_chunk *chunk;
        struct sctp_association *asoc;
@@ -165,7 +166,6 @@ SCTP_ARG_CONSTRUCTOR(U16,   __u16, u16)
 SCTP_ARG_CONSTRUCTOR(U8,       __u8, u8)
 SCTP_ARG_CONSTRUCTOR(ERROR,     int, error)
 SCTP_ARG_CONSTRUCTOR(STATE,    sctp_state_t, state)
-SCTP_ARG_CONSTRUCTOR(COUNTER,  sctp_counter_t, counter)
 SCTP_ARG_CONSTRUCTOR(TO,       sctp_event_timeout_t, to)
 SCTP_ARG_CONSTRUCTOR(PTR,      void *, ptr)
 SCTP_ARG_CONSTRUCTOR(CHUNK,    struct sctp_chunk *, chunk)
index 2b76c0f4babc7c747b8fbedf7bbb6447e0bea841..4868c7f7749dab76a2abbffdf81ca28e2d0609b8 100644 (file)
@@ -263,13 +263,6 @@ enum { SCTP_MIN_PMTU = 576 };
 enum { SCTP_MAX_DUP_TSNS = 16 };
 enum { SCTP_MAX_GABS = 16 };
 
-typedef enum {
-       SCTP_COUNTER_INIT_ERROR,
-} sctp_counter_t;
-
-/* How many counters does an association need? */
-#define SCTP_NUMBER_COUNTERS   5
-
 /* Here we define the default timers.  */
 
 /* cookie timer def = ? seconds */
index 960abfa48d6819215c30091112a25642c72ab872..ef2738159ab344e4291411980dae856d7c02c619 100644 (file)
@@ -223,6 +223,22 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
 extern int sctp_debug_flag;
 #define SCTP_DEBUG_PRINTK(whatever...) \
        ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever)))
+#define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \
+       if (sctp_debug_flag) { \
+               if (saddr->sa.sa_family == AF_INET6) { \
+                       printk(KERN_DEBUG \
+                              lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \
+                              leadparm, \
+                              NIP6(saddr->v6.sin6_addr), \
+                              otherparms); \
+               } else { \
+                       printk(KERN_DEBUG \
+                              lead "%u.%u.%u.%u" trail, \
+                              leadparm, \
+                              NIPQUAD(saddr->v4.sin_addr.s_addr), \
+                              otherparms); \
+               } \
+       }
 #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
 #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }
 
@@ -236,6 +252,7 @@ extern int sctp_debug_flag;
 #else  /* SCTP_DEBUG */
 
 #define SCTP_DEBUG_PRINTK(whatever...)
+#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
 #define SCTP_ENABLE_DEBUG
 #define SCTP_DISABLE_DEBUG
 #define SCTP_ASSERT(expr, str, func)
index f4fcee104707ae7961605b632aba1bf620c25603..a53e08a45e32fb8e3c271f30d5792b1a7e567cf1 100644 (file)
@@ -116,7 +116,8 @@ sctp_state_fn_t sctp_sf_eat_data_fast_4_4;
 sctp_state_fn_t sctp_sf_eat_sack_6_2;
 sctp_state_fn_t sctp_sf_tabort_8_4_8;
 sctp_state_fn_t sctp_sf_operr_notify;
-sctp_state_fn_t sctp_sf_t1_timer_expire;
+sctp_state_fn_t sctp_sf_t1_init_timer_expire;
+sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
 sctp_state_fn_t sctp_sf_t2_timer_expire;
 sctp_state_fn_t sctp_sf_t4_timer_expire;
 sctp_state_fn_t sctp_sf_t5_timer_expire;
@@ -258,7 +259,10 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error);
+sctp_disposition_t  sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+                                          __u16 error,
+                                          const struct sctp_association *asoc,
+                                          struct sctp_transport *transport);
 
 /* Prototypes for statetable processing. */
 
index 6c24d9cd3d66c2849dbcfe544c0739232bb4e690..dfad4d3c581c483c149321df4346b6e52532cacb 100644 (file)
@@ -867,10 +867,13 @@ struct sctp_transport {
         */
        unsigned long last_time_ecne_reduced;
 
-       /* active      : The current active state of this destination,
-        *             :  i.e. DOWN, UP, etc.
+       /* The number of times INIT has been sent on this transport. */
+       int init_sent_count;
+
+       /* state       : The current state of this destination,
+        *             : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN.
         */
-       int active;
+       int state;
 
        /* hb_allowed  : The current heartbeat state of this destination,
         *             :  i.e. ALLOW-HB, NO-HEARTBEAT, etc.
@@ -1222,9 +1225,6 @@ struct sctp_endpoint {
 
        /* sendbuf acct. policy.        */
        __u32 sndbuf_policy;
-
-       /* Name for debugging output... */
-       char *debug_name;
 };
 
 /* Recover the outter endpoint structure. */
@@ -1314,11 +1314,23 @@ struct sctp_association {
                 *             : association. Normally this information is
                 *             : hashed or keyed for quick lookup and access
                 *             : of the TCB.
+                *             : The list is also initialized with the list
+                *             : of addresses passed with the sctp_connectx()
+                *             : call.
                 *
                 * It is a list of SCTP_transport's.
                 */
                struct list_head transport_addr_list;
 
+               /* transport_count
+                *
+                * Peer        : A count of the number of peer addresses
+                * Transport   : in the Peer Transport Address List.
+                * Address     :
+                * Count       :
+                */
+               __u16 transport_count;
+
                /* port
                 *   The transport layer port number.
                 */
@@ -1486,6 +1498,9 @@ struct sctp_association {
        /* Transport to which SHUTDOWN chunk was last sent.  */
        struct sctp_transport *shutdown_last_sent_to;
 
+       /* Transport to which INIT chunk was last sent.  */
+       struct sctp_transport *init_last_sent_to;
+
        /* Next TSN    : The next TSN number to be assigned to a new
         *             : DATA chunk.  This is sent in the INIT or INIT
         *             : ACK chunk to the peer and incremented each
@@ -1549,8 +1564,11 @@ struct sctp_association {
        /* The message size at which SCTP fragmentation will occur. */
        __u32 frag_point;
 
-       /* Currently only one counter is used to count INIT errors. */
-       int counters[SCTP_NUMBER_COUNTERS];
+       /* Counter used to count INIT errors. */
+       int init_err_counter;
+
+       /* Count the number of INIT cycles (for doubling timeout). */
+       int init_cycle;
 
        /* Default send parameters. */
        __u16 default_stream;
@@ -1708,6 +1726,8 @@ void sctp_association_free(struct sctp_association *);
 void sctp_association_put(struct sctp_association *);
 void sctp_association_hold(struct sctp_association *);
 
+struct sctp_transport *sctp_assoc_choose_init_transport(
+       struct sctp_association *);
 struct sctp_transport *sctp_assoc_choose_shutdown_transport(
        struct sctp_association *);
 void sctp_assoc_update_retran_path(struct sctp_association *);
@@ -1717,9 +1737,12 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
                            const union sctp_addr *laddr);
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
                                     const union sctp_addr *address,
-                                    const int gfp);
+                                    const int gfp,
+                                    const int peer_state);
 void sctp_assoc_del_peer(struct sctp_association *asoc,
                         const union sctp_addr *addr);
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+                        struct sctp_transport *peer);
 void sctp_assoc_control_transport(struct sctp_association *,
                                  struct sctp_transport *,
                                  sctp_transport_cmd_t, sctp_sn_error_t);
index 2758e8ce4f25c30b2c7b7e84c7e27b5485198462..f6328aeddcce064a9eebd2c570ede0a2b5b1d33e 100644 (file)
@@ -111,6 +111,8 @@ enum sctp_optname {
 #define SCTP_GET_LOCAL_ADDRS_NUM       SCTP_GET_LOCAL_ADDRS_NUM
        SCTP_GET_LOCAL_ADDRS,   /* Get all local addresss. */
 #define SCTP_GET_LOCAL_ADDRS   SCTP_GET_LOCAL_ADDRS
+       SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
+#define SCTP_SOCKOPT_CONNECTX  SCTP_SOCKOPT_CONNECTX
 };
 
 /*
@@ -527,6 +529,7 @@ struct sctp_paddrinfo {
 enum sctp_spinfo_state {
        SCTP_INACTIVE,
        SCTP_ACTIVE,
+       SCTP_UNKNOWN = 0xffff  /* Value used for transport state unknown */
 };
 
 /*
index 0e65e02b7a1d3f2a396d370142119e159b5defc7..029522a4cedab6c3f5ef61f56ce61cb5fe4714e4 100644 (file)
@@ -204,6 +204,7 @@ struct xfrm_state_afinfo {
        rwlock_t                lock;
        struct list_head        *state_bydst;
        struct list_head        *state_byspi;
+       int                     (*init_flags)(struct xfrm_state *x);
        void                    (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
                                                struct xfrm_tmpl *tmpl,
                                                xfrm_address_t *daddr, xfrm_address_t *saddr);
@@ -225,7 +226,7 @@ struct xfrm_type
        struct module           *owner;
        __u8                    proto;
 
-       int                     (*init_state)(struct xfrm_state *x, void *args);
+       int                     (*init_state)(struct xfrm_state *x);
        void                    (*destructor)(struct xfrm_state *);
        int                     (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
        int                     (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
@@ -839,6 +840,7 @@ extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+extern int xfrm_init_state(struct xfrm_state *x);
 extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
index 54640c01b50cddcbf3f42321361c08b9ebe911c4..10d040461021271e127e28d3bea365ababc6c037 100644 (file)
@@ -565,7 +565,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
                         *      numbers we just happen to need. Now put the
                         *      length in the lower two.
                         */
-                       *((__u16 *)skb->data) = htons(skb->len);
+                       *((__be16 *)skb->data) = htons(skb->len);
                        ft = 1;
                }
                /*
index 876dbac71060860956f2e939c81efe2b91512775..192b529f86a456e62864867d9a219b5eabb7f796 100644 (file)
@@ -401,7 +401,7 @@ out_err:
 }
 
 /* Find a match for a specific network:node pair */
-static struct atalk_iface *atalk_find_interface(int net, int node)
+static struct atalk_iface *atalk_find_interface(__be16 net, int node)
 {
        struct atalk_iface *iface;
 
index 0e98f2235b6e1edc5f35504e23e76ab5bad27aed..514c85b2631a3332187141c2afdd7ed7825314cb 100644 (file)
@@ -200,7 +200,7 @@ static void ah4_err(struct sk_buff *skb, u32 info)
        xfrm_state_put(x);
 }
 
-static int ah_init_state(struct xfrm_state *x, void *args)
+static int ah_init_state(struct xfrm_state *x)
 {
        struct ah_data *ahp = NULL;
        struct xfrm_algo_desc *aalg_desc;
index eae84cc39d3f10e984c93e11cb4a94c160bc6a80..ba57446d5d1f4a1831f926859dca12c40369067e 100644 (file)
@@ -362,7 +362,7 @@ static void esp_destroy(struct xfrm_state *x)
        kfree(esp);
 }
 
-static int esp_init_state(struct xfrm_state *x, void *args)
+static int esp_init_state(struct xfrm_state *x)
 {
        struct esp_data *esp = NULL;
 
index 563e7d61270612b64a5f67684c5eea1662b66a31..cd8e45ab95807116a18fe1649422766ef636da3c 100644 (file)
@@ -516,6 +516,60 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
 #undef BRD1_OK
 }
 
+static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
+{
+       
+       struct fib_result       res;
+       struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, 
+                                                           .fwmark = frn->fl_fwmark,
+                                                           .tos = frn->fl_tos,
+                                                           .scope = frn->fl_scope } } };
+       if (tb) {
+               local_bh_disable();
+
+               frn->tb_id = tb->tb_id;
+               frn->err = tb->tb_lookup(tb, &fl, &res);
+
+               if (!frn->err) {
+                       frn->prefixlen = res.prefixlen;
+                       frn->nh_sel = res.nh_sel;
+                       frn->type = res.type;
+                       frn->scope = res.scope;
+               }
+               local_bh_enable();
+       }
+}
+
+static void nl_fib_input(struct sock *sk, int len)
+{
+       struct sk_buff *skb = NULL;
+        struct nlmsghdr *nlh = NULL;
+       struct fib_result_nl *frn;
+       int err;
+       u32 pid;     
+       struct fib_table *tb;
+       
+       skb = skb_recv_datagram(sk, 0, 0, &err);
+       nlh = (struct nlmsghdr *)skb->data;
+       
+       frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
+       tb = fib_get_table(frn->tb_id_in);
+
+       nl_fib_lookup(frn, tb);
+       
+       pid = nlh->nlmsg_pid;           /*pid of sending process */
+       NETLINK_CB(skb).groups = 0;     /* not in mcast group */
+       NETLINK_CB(skb).pid = 0;         /* from kernel */
+       NETLINK_CB(skb).dst_pid = pid;
+       NETLINK_CB(skb).dst_groups = 0;  /* unicast */
+       netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
+}    
+
+static void nl_fib_lookup_init(void)
+{
+      netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input);
+}
+
 static void fib_disable_ip(struct net_device *dev, int force)
 {
        if (fib_sync_down(0, dev, force))
@@ -604,6 +658,7 @@ void __init ip_fib_init(void)
 
        register_netdevice_notifier(&fib_netdev_notifier);
        register_inetaddr_notifier(&fib_inetaddr_notifier);
+       nl_fib_lookup_init();
 }
 
 EXPORT_SYMBOL(inet_addr_type);
index 1a23c5263b993a9004aea0518216de263178f63b..2065944fd9e5117739ed1f2aeed2c2c59cf50151 100644 (file)
@@ -236,15 +236,10 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
        t->props.mode = 1;
        t->props.saddr.a4 = x->props.saddr.a4;
        t->props.flags = x->props.flags;
-       
-       t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family);
-       if (t->type == NULL)
-               goto error;
-               
-       if (t->type->init_state(t, NULL))
+
+       if (xfrm_init_state(t))
                goto error;
 
-       t->km.state = XFRM_STATE_VALID;
        atomic_set(&t->tunnel_users, 1);
 out:
        return t;
@@ -422,7 +417,7 @@ static void ipcomp_destroy(struct xfrm_state *x)
        kfree(ipcd);
 }
 
-static int ipcomp_init_state(struct xfrm_state *x, void *args)
+static int ipcomp_init_state(struct xfrm_state *x)
 {
        int err;
        struct ipcomp_data *ipcd;
index af2392ae576965e60ec55f59e17b78167f2d0cbe..66620a95942a5f3f05f0964883eb358706130964 100644 (file)
@@ -33,6 +33,7 @@ static void xfrm4_encap(struct sk_buff *skb)
        struct dst_entry *dst = skb->dst;
        struct xfrm_state *x = dst->xfrm;
        struct iphdr *iph, *top_iph;
+       int flags;
 
        iph = skb->nh.iph;
        skb->h.ipiph = iph;
@@ -51,10 +52,13 @@ static void xfrm4_encap(struct sk_buff *skb)
 
        /* DS disclosed */
        top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
-       if (x->props.flags & XFRM_STATE_NOECN)
+
+       flags = x->props.flags;
+       if (flags & XFRM_STATE_NOECN)
                IP_ECN_clear(top_iph);
 
-       top_iph->frag_off = iph->frag_off & htons(IP_DF);
+       top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+               0 : (iph->frag_off & htons(IP_DF));
        if (!top_iph->frag_off)
                __ip_select_ident(top_iph, dst, 0);
 
index 223a2e83853f9d6e6c8bb8802498bf907cf32d79..050611d7a9670d178c37cc6a835fd7503f0117b9 100644 (file)
@@ -7,12 +7,20 @@
  *
  */
 
+#include <net/ip.h>
 #include <net/xfrm.h>
 #include <linux/pfkeyv2.h>
 #include <linux/ipsec.h>
 
 static struct xfrm_state_afinfo xfrm4_state_afinfo;
 
+static int xfrm4_init_flags(struct xfrm_state *x)
+{
+       if (ipv4_config.no_pmtu_disc)
+               x->props.flags |= XFRM_STATE_NOPMTUDISC;
+       return 0;
+}
+
 static void
 __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
                     struct xfrm_tmpl *tmpl,
@@ -109,6 +117,7 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
 static struct xfrm_state_afinfo xfrm4_state_afinfo = {
        .family                 = AF_INET,
        .lock                   = RW_LOCK_UNLOCKED,
+       .init_flags             = xfrm4_init_flags,
        .init_tempsel           = __xfrm4_init_tempsel,
        .state_lookup           = __xfrm4_state_lookup,
        .find_acq               = __xfrm4_find_acq,
index 413191f585f6a15656defcc90acdc9b856d397e7..e1fe360ed27ad1645a861c07ddabd2293694f694 100644 (file)
@@ -84,7 +84,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
                handler->err_handler(skb, &arg);
 }
 
-static int ipip_init_state(struct xfrm_state *x, void *args)
+static int ipip_init_state(struct xfrm_state *x)
 {
        if (!x->props.mode)
                return -EINVAL;
index e3ecf626cbf7944cded30013de71bb25fe190adc..986fdfdccbcdee96a9f2b7d014fa7575ae4bd386 100644 (file)
@@ -339,7 +339,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        xfrm_state_put(x);
 }
 
-static int ah6_init_state(struct xfrm_state *x, void *args)
+static int ah6_init_state(struct xfrm_state *x)
 {
        struct ah_data *ahp = NULL;
        struct xfrm_algo_desc *aalg_desc;
index be7095d6babefaad31d81b57338ded650f0f8eec..324db62515a29e88c51c3fff9fe48e2960ac51da 100644 (file)
@@ -296,7 +296,7 @@ static void esp6_destroy(struct xfrm_state *x)
        kfree(esp);
 }
 
-static int esp6_init_state(struct xfrm_state *x, void *args)
+static int esp6_init_state(struct xfrm_state *x)
 {
        struct esp_data *esp = NULL;
 
index 6cde5310cd76b195264b6829725288d91c6d995d..423feb46ccc026841ea52ef771d8f85842944dc1 100644 (file)
@@ -234,14 +234,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
        t->props.mode = 1;
        memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
 
-       t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family);
-       if (t->type == NULL)
+       if (xfrm_init_state(t))
                goto error;
 
-       if (t->type->init_state(t, NULL))
-               goto error;
-
-       t->km.state = XFRM_STATE_VALID;
        atomic_set(&t->tunnel_users, 1);
 
 out:
@@ -420,7 +415,7 @@ static void ipcomp6_destroy(struct xfrm_state *x)
        xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
 }
 
-static int ipcomp6_init_state(struct xfrm_state *x, void *args)
+static int ipcomp6_init_state(struct xfrm_state *x)
 {
        int err;
        struct ipcomp_data *ipcd;
index ffcadd68b951df9f08610bcf0fbcd7b497dea7d0..60c26c87277e7fa63a34f9b8671cbdd79efb1fd4 100644 (file)
@@ -466,7 +466,7 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        return;
 }
 
-static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
+static int xfrm6_tunnel_init_state(struct xfrm_state *x)
 {
        if (!x->props.mode)
                return -EINVAL;
index 98b72f2024ffd84564530e5973861b908fd8f541..4879743b945ae5956c6713a6c50dc5a2052f37ae 100644 (file)
@@ -690,6 +690,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
                sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;
        if (x->props.flags & XFRM_STATE_DECAP_DSCP)
                sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;
+       if (x->props.flags & XFRM_STATE_NOPMTUDISC)
+               sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC;
 
        /* hard time */
        if (hsc & 2) {
@@ -974,6 +976,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
                x->props.flags |= XFRM_STATE_NOECN;
        if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
                x->props.flags |= XFRM_STATE_DECAP_DSCP;
+       if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
+               x->props.flags |= XFRM_STATE_NOPMTUDISC;
 
        lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
        if (lifetime != NULL) {
@@ -1096,17 +1100,11 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
                }
        }
 
-       x->type = xfrm_get_type(proto, x->props.family);
-       if (x->type == NULL) {
-               err = -ENOPROTOOPT;
-               goto out;
-       }
-       if (x->type->init_state(x, NULL)) {
-               err = -EINVAL;
+       err = xfrm_init_state(x);
+       if (err)
                goto out;
-       }
+
        x->km.seq = hdr->sadb_msg_seq;
-       x->km.state = XFRM_STATE_VALID;
        return x;
 
 out:
index 663843d97a921e7ca88ef5df82154f7b95227751..7ae6aa772dab76388a70d22e19e74e76b3a215e9 100644 (file)
@@ -191,10 +191,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->last_cwr_tsn = asoc->ctsn_ack_point;
        asoc->unack_data = 0;
 
-       SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n",
-                         asoc->ep->debug_name,
-                         asoc->ctsn_ack_point);
-
        /* ADDIP Section 4.1 Asconf Chunk Procedures
         *
         * When an endpoint has an ASCONF signaled change to be sent to the
@@ -211,6 +207,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        /* Make an empty list of remote transport addresses.  */
        INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
+       asoc->peer.transport_count = 0;
 
        /* RFC 2960 5.1 Normal Establishment of an Association
         *
@@ -288,6 +285,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
 
        asoc->base.malloced = 1;
        SCTP_DBG_OBJCNT_INC(assoc);
+       SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc);
 
        return asoc;
 
@@ -356,6 +354,8 @@ void sctp_association_free(struct sctp_association *asoc)
                sctp_transport_free(transport);
        }
 
+       asoc->peer.transport_count = 0;
+
        /* Free any cached ASCONF_ACK chunk. */
        if (asoc->addip_last_asconf_ack)
                sctp_chunk_free(asoc->addip_last_asconf_ack);
@@ -400,7 +400,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
        /* If the primary path is changing, assume that the
         * user wants to use this new path.
         */
-       if (transport->active)
+       if (transport->state != SCTP_INACTIVE)
                asoc->peer.active_path = transport;
 
        /*
@@ -428,10 +428,58 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
        transport->cacc.next_tsn_at_change = asoc->next_tsn;
 }
 
+/* Remove a transport from an association.  */
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+                       struct sctp_transport *peer)
+{
+       struct list_head        *pos;
+       struct sctp_transport   *transport;
+
+       SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ",
+                                " port: %d\n",
+                                asoc,
+                                (&peer->ipaddr),
+                                peer->ipaddr.v4.sin_port);
+
+       /* If we are to remove the current retran_path, update it
+        * to the next peer before removing this peer from the list.
+        */
+       if (asoc->peer.retran_path == peer)
+               sctp_assoc_update_retran_path(asoc);
+
+       /* Remove this peer from the list. */
+       list_del(&peer->transports);
+
+       /* Get the first transport of asoc. */
+       pos = asoc->peer.transport_addr_list.next;
+       transport = list_entry(pos, struct sctp_transport, transports);
+
+       /* Update any entries that match the peer to be deleted. */
+       if (asoc->peer.primary_path == peer)
+               sctp_assoc_set_primary(asoc, transport);
+       if (asoc->peer.active_path == peer)
+               asoc->peer.active_path = transport;
+       if (asoc->peer.last_data_from == peer)
+               asoc->peer.last_data_from = transport;
+
+       /* If we remove the transport an INIT was last sent to, set it to
+        * NULL. Combined with the update of the retran path above, this
+        * will cause the next INIT to be sent to the next available
+        * transport, maintaining the cycle.
+        */
+       if (asoc->init_last_sent_to == peer)
+               asoc->init_last_sent_to = NULL;
+
+       asoc->peer.transport_count--;
+
+       sctp_transport_free(peer);
+}
+
 /* Add a transport address to an association.  */
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
                                           const union sctp_addr *addr,
-                                          int gfp)
+                                          const int gfp,
+                                          const int peer_state)
 {
        struct sctp_transport *peer;
        struct sctp_sock *sp;
@@ -442,14 +490,25 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
        /* AF_INET and AF_INET6 share common port field. */
        port = addr->v4.sin_port;
 
+       SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
+                                " port: %d state:%s\n",
+                                asoc,
+                                addr,
+                                addr->v4.sin_port,
+                                peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
+
        /* Set the port if it has not been set yet.  */
        if (0 == asoc->peer.port)
                asoc->peer.port = port;
 
        /* Check to see if this is a duplicate. */
        peer = sctp_assoc_lookup_paddr(asoc, addr);
-       if (peer)
+       if (peer) {
+               if (peer_state == SCTP_ACTIVE &&
+                   peer->state == SCTP_UNKNOWN)
+                    peer->state = SCTP_ACTIVE;
                return peer;
+       }
 
        peer = sctp_transport_new(addr, gfp);
        if (!peer)
@@ -516,8 +575,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
        /* Set the transport's RTO.initial value */
        peer->rto = asoc->rto_initial;
 
+       /* Set the peer's active state. */
+       peer->state = peer_state;
+
        /* Attach the remote transport to our asoc.  */
        list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+       asoc->peer.transport_count++;
 
        /* If we do not yet have a primary path, set one.  */
        if (!asoc->peer.primary_path) {
@@ -525,8 +588,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
                asoc->peer.retran_path = peer;
        }
 
-       if (asoc->peer.active_path == asoc->peer.retran_path)
+       if (asoc->peer.active_path == asoc->peer.retran_path) {
                asoc->peer.retran_path = peer;
+       }
 
        return peer;
 }
@@ -537,37 +601,16 @@ void sctp_assoc_del_peer(struct sctp_association *asoc,
 {
        struct list_head        *pos;
        struct list_head        *temp;
-       struct sctp_transport   *peer = NULL;
        struct sctp_transport   *transport;
 
        list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
                transport = list_entry(pos, struct sctp_transport, transports);
                if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) {
-                       peer = transport;
-                       list_del(pos);
+                       /* Do book keeping for removing the peer and free it. */
+                       sctp_assoc_rm_peer(asoc, transport);
                        break;
                }
        }
-
-       /* The address we want delete is not in the association. */
-       if (!peer)
-               return;
-
-       /* Get the first transport of asoc. */ 
-       pos = asoc->peer.transport_addr_list.next;
-       transport = list_entry(pos, struct sctp_transport, transports);
-
-       /* Update any entries that match the peer to be deleted. */  
-       if (asoc->peer.primary_path == peer)
-               sctp_assoc_set_primary(asoc, transport);
-       if (asoc->peer.active_path == peer)
-               asoc->peer.active_path = transport;
-       if (asoc->peer.retran_path == peer)
-               asoc->peer.retran_path = transport;
-       if (asoc->peer.last_data_from == peer)
-               asoc->peer.last_data_from = transport;
-
-       sctp_transport_free(peer);
 }
 
 /* Lookup a transport by address. */
@@ -608,12 +651,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
        /* Record the transition on the transport.  */
        switch (command) {
        case SCTP_TRANSPORT_UP:
-               transport->active = SCTP_ACTIVE;
+               transport->state = SCTP_ACTIVE;
                spc_state = SCTP_ADDR_AVAILABLE;
                break;
 
        case SCTP_TRANSPORT_DOWN:
-               transport->active = SCTP_INACTIVE;
+               transport->state = SCTP_INACTIVE;
                spc_state = SCTP_ADDR_UNREACHABLE;
                break;
 
@@ -643,7 +686,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
        list_for_each(pos, &asoc->peer.transport_addr_list) {
                t = list_entry(pos, struct sctp_transport, transports);
 
-               if (!t->active)
+               if (t->state == SCTP_INACTIVE)
                        continue;
                if (!first || t->last_time_heard > first->last_time_heard) {
                        second = first;
@@ -663,7 +706,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
         * [If the primary is active but not most recent, bump the most
         * recently used transport.]
         */
-       if (asoc->peer.primary_path->active &&
+       if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
            first != asoc->peer.primary_path) {
                second = first;
                first = asoc->peer.primary_path;
@@ -958,7 +1001,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
                                           transports);
                        if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
                                sctp_assoc_add_peer(asoc, &trans->ipaddr,
-                                                   GFP_ATOMIC);
+                                                   GFP_ATOMIC, SCTP_ACTIVE);
                }
 
                asoc->ctsn_ack_point = asoc->next_tsn - 1;
@@ -998,7 +1041,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
 
                /* Try to find an active transport. */
 
-               if (t->active) {
+               if (t->state != SCTP_INACTIVE) {
                        break;
                } else {
                        /* Keep track of the next transport in case
@@ -1019,6 +1062,40 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
        }
 
        asoc->peer.retran_path = t;
+
+       SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+                                " %p addr: ",
+                                " port: %d\n",
+                                asoc,
+                                (&t->ipaddr),
+                                t->ipaddr.v4.sin_port);
+}
+
+/* Choose the transport for sending a INIT packet.  */
+struct sctp_transport *sctp_assoc_choose_init_transport(
+       struct sctp_association *asoc)
+{
+       struct sctp_transport *t;
+
+       /* Use the retran path. If the last INIT was sent over the
+        * retran path, update the retran path and use it.
+        */
+       if (!asoc->init_last_sent_to) {
+               t = asoc->peer.active_path;
+       } else {
+               if (asoc->init_last_sent_to == asoc->peer.retran_path)
+                       sctp_assoc_update_retran_path(asoc);
+               t = asoc->peer.retran_path;
+       }
+
+       SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+                                " %p addr: ",
+                                " port: %d\n",
+                                asoc,
+                                (&t->ipaddr),
+                                t->ipaddr.v4.sin_port);
+
+       return t;
 }
 
 /* Choose the transport for sending a SHUTDOWN packet.  */
index 334f61773e6d692844aab739df7ca0084f54ab1c..2ec0320fac3b5634bbd62e6f8905d179314431ce 100644 (file)
@@ -134,7 +134,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
        ep->last_key = ep->current_key = 0;
        ep->key_changed_at = jiffies;
 
-       ep->debug_name = "unnamedEndpoint";
        return ep;
 }
 
index fffc880a646d9a027a690bef279ff81e1e1ee162..339f7acfdb647b7eca56aa43c2a35e0aa9afb735 100644 (file)
@@ -353,7 +353,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
 
        sctp_do_sm(SCTP_EVENT_T_OTHER,
                   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
-                  asoc->state, asoc->ep, asoc, NULL,
+                  asoc->state, asoc->ep, asoc, t,
                   GFP_ATOMIC);
 
 }
index 1b2d4adc4ddbaf013e802d8e1da8df756d395e77..4eb81a1407b7e027c7da1302a8af43705be3015a 100644 (file)
@@ -682,9 +682,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                if (!new_transport) {
                        new_transport = asoc->peer.active_path;
-               } else if (!new_transport->active) {
-                       /* If the chunk is Heartbeat or Heartbeat Ack, 
-                        * send it to chunk->transport, even if it's 
+               } else if (new_transport->state == SCTP_INACTIVE) {
+                       /* If the chunk is Heartbeat or Heartbeat Ack,
+                        * send it to chunk->transport, even if it's
                         * inactive.
                         *
                         * 3.3.6 Heartbeat Acknowledgement:
@@ -840,7 +840,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
                         * Otherwise, we want to use the active path.
                         */
                        new_transport = chunk->transport;
-                       if (!new_transport || !new_transport->active)
+                       if (!new_transport ||
+                           new_transport->state == SCTP_INACTIVE)
                                new_transport = asoc->peer.active_path;
 
                        /* Change packets if necessary.  */
@@ -1454,7 +1455,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                        /* Mark the destination transport address as
                         * active if it is not so marked.
                         */
-                       if (!transport->active) {
+                       if (transport->state == SCTP_INACTIVE) {
                                sctp_assoc_control_transport(
                                        transport->asoc,
                                        transport,
index 33ac8bf47b0e0d64b2ba9a75b136bc82eac1fa65..5baed9bb7de51a64c7cfede056ac0ccdf5ede850 100644 (file)
@@ -1830,7 +1830,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
         * be a a better choice than any of the embedded addresses.
         */
        if (peer_addr)
-               if(!sctp_assoc_add_peer(asoc, peer_addr, gfp))
+               if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
                        goto nomem;
 
        /* Process the initialization parameters.  */
@@ -1841,6 +1841,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
                         goto clean_up;
        }
 
+       /* Walk list of transports, removing transports in the UNKNOWN state. */
+       list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
+               transport = list_entry(pos, struct sctp_transport, transports);
+               if (transport->state == SCTP_UNKNOWN) {
+                       sctp_assoc_rm_peer(asoc, transport);
+               }
+       }
+
        /* The fixed INIT headers are always in network byte
         * order.
         */
@@ -1906,7 +1914,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
         * stream sequence number shall be set to 0.
         */
 
-       /* Allocate storage for the negotiated streams if it is not a temporary          * association.
+       /* Allocate storage for the negotiated streams if it is not a temporary
+        * association.
         */
        if (!asoc->temp) {
                int assoc_id;
@@ -1952,6 +1961,9 @@ clean_up:
                list_del_init(pos);
                sctp_transport_free(transport);
        }
+
+       asoc->peer.transport_count = 0;
+
 nomem:
        return 0;
 }
@@ -1995,7 +2007,7 @@ static int sctp_process_param(struct sctp_association *asoc,
                af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
                scope = sctp_scope(peer_addr);
                if (sctp_in_scope(&addr, scope))
-                       if (!sctp_assoc_add_peer(asoc, &addr, gfp))
+                       if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
                                return 0;
                break;
 
@@ -2396,7 +2408,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
                 * Due to Resource Shortage'.
                 */
 
-               peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC);
+               peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE);
                if (!peer)
                        return SCTP_ERROR_RSRC_LOW;
 
index f65fa441952f7bbcd3b3b57c6f98468e16112eca..778639db125a2d53e1be5fd3b785af64ffbba8c3 100644 (file)
@@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
         */
        asoc->overall_error_count++;
 
-       if (transport->active &&
+       if (transport->state != SCTP_INACTIVE &&
            (transport->error_count++ >= transport->max_retrans)) {
-               SCTP_DEBUG_PRINTK("transport_strike: transport "
-                                 "IP:%d.%d.%d.%d failed.\n",
-                                 NIPQUAD(transport->ipaddr.v4.sin_addr));
+               SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
+                                        " transport IP: port:%d failed.\n",
+                                        asoc,
+                                        (&transport->ipaddr),
+                                        transport->ipaddr.v4.sin_port);
                sctp_assoc_control_transport(asoc, transport,
                                             SCTP_TRANSPORT_DOWN,
                                             SCTP_FAILED_THRESHOLD);
@@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
        /* Mark the destination transport address as active if it is not so
         * marked.
         */
-       if (!t->active)
+       if (t->state == SCTP_INACTIVE)
                sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
                                             SCTP_HEARTBEAT_SUCCESS);
 
@@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
 
        asoc->state = state;
 
+       SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n",
+                         asoc, sctp_state_tbl[state]);
+
        if (sctp_style(sk, TCP)) {
-               /* Change the sk->sk_state of a TCP-style socket that has 
+               /* Change the sk->sk_state of a TCP-style socket that has
                 * sucessfully completed a connect() call.
                 */
                if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED))
@@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
                        sk->sk_shutdown |= RCV_SHUTDOWN;
        }
 
+       if (sctp_state(asoc, COOKIE_WAIT)) {
+               /* Reset init timeouts since they may have been
+                * increased due to timer expirations.
+                */
+               asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+                       asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT];
+               asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
+                       asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE];
+       }
+
        if (sctp_state(asoc, ESTABLISHED) ||
            sctp_state(asoc, CLOSED) ||
            sctp_state(asoc, SHUTDOWN_RECEIVED)) {
@@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                         * to be executed only during failed attempts of
                         * association establishment.
                         */
-                       if ((asoc->peer.retran_path != 
-                            asoc->peer.primary_path) && 
-                           (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) {
-                               sctp_add_cmd_sf(commands, 
+                       if ((asoc->peer.retran_path !=
+                            asoc->peer.primary_path) &&
+                           (asoc->init_err_counter > 0)) {
+                               sctp_add_cmd_sf(commands,
                                                SCTP_CMD_FORCE_PRIM_RETRAN,
                                                SCTP_NULL());
                        }
@@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                sctp_association_put(asoc);
                        break;
 
+               case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
+                       chunk = cmd->obj.ptr;
+                       t = sctp_assoc_choose_init_transport(asoc);
+                       asoc->init_last_sent_to = t;
+                       chunk->transport = t;
+                       t->init_sent_count++;
+                       break;
+
                case SCTP_CMD_INIT_RESTART:
                        /* Do the needed accounting and updates
                         * associated with restarting an initialization
-                        * timer.
+                        * timer. Only multiply the timeout by two if
+                        * all transports have been tried at the current
+                        * timeout.
+                        */
+                       t = asoc->init_last_sent_to;
+                       asoc->init_err_counter++;
+
+                       if (t->init_sent_count > (asoc->init_cycle + 1)) {
+                               asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2;
+                               if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] >
+                                   asoc->max_init_timeo) {
+                                       asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+                                               asoc->max_init_timeo;
+                               }
+                               asoc->init_cycle++;
+                               SCTP_DEBUG_PRINTK(
+                                       "T1 INIT Timeout adjustment"
+                                       " init_err_counter: %d"
+                                       " cycle: %d"
+                                       " timeout: %d\n",
+                                       asoc->init_err_counter,
+                                       asoc->init_cycle,
+                                       asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
+                       }
+
+                       sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
+                                       SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+                       break;
+
+               case SCTP_CMD_COOKIEECHO_RESTART:
+                       /* Do the needed accounting and updates
+                        * associated with restarting an initialization
+                        * timer. Only multiply the timeout by two if
+                        * all transports have been tried at the current
+                        * timeout.
                         */
-                       asoc->counters[SCTP_COUNTER_INIT_ERROR]++;
-                       asoc->timeouts[cmd->obj.to] *= 2;
-                       if (asoc->timeouts[cmd->obj.to] >
+                       asoc->init_err_counter++;
+
+                       asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2;
+                       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] >
                            asoc->max_init_timeo) {
-                               asoc->timeouts[cmd->obj.to] =
+                               asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
                                        asoc->max_init_timeo;
                        }
+                       SCTP_DEBUG_PRINTK(
+                               "T1 COOKIE Timeout adjustment"
+                               " init_err_counter: %d"
+                               " timeout: %d\n",
+                               asoc->init_err_counter,
+                               asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
 
                        /* If we've sent any data bundled with
                         * COOKIE-ECHO we need to resend.
@@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 
                        sctp_add_cmd_sf(commands,
                                        SCTP_CMD_TIMER_RESTART,
-                                       SCTP_TO(cmd->obj.to));
+                                       SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
                        break;
 
                case SCTP_CMD_INIT_FAILED:
@@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                              subtype, chunk, cmd->obj.u32);
                        break;
 
-               case SCTP_CMD_COUNTER_INC:
-                       asoc->counters[cmd->obj.counter]++;
+               case SCTP_CMD_INIT_COUNTER_INC:
+                       asoc->init_err_counter++;
                        break;
 
-               case SCTP_CMD_COUNTER_RESET:
-                       asoc->counters[cmd->obj.counter] = 0;
+               case SCTP_CMD_INIT_COUNTER_RESET:
+                       asoc->init_err_counter = 0;
+                       asoc->init_cycle = 0;
                        break;
 
                case SCTP_CMD_REPORT_DUP:
index 8e01b8f09ac28914573c81727d9e19ab55076652..058189684c7ce0dbf0cc489c1566fcd1fabf5e28 100644 (file)
@@ -533,6 +533,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT,
                        SCTP_PEER_INIT(initchunk));
 
+       /* Reset init error count upon receipt of INIT-ACK.  */
+       sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
+
        /* 5.1 C) "A" shall stop the T1-init timer and leave
         * COOKIE-WAIT state.  "A" shall then ... start the T1-cookie
         * timer, and enter the COOKIE-ECHOED state.
@@ -775,8 +778,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
         * from the COOKIE-ECHOED state to the COOKIE-WAIT
         * state is performed.
         */
-       sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
-                       SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+       sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
 
        /* RFC 2960 5.1 Normal Establishment of an Association
         *
@@ -1019,10 +1021,22 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
        link = sctp_assoc_lookup_paddr(asoc, &from_addr);
 
        /* This should never happen, but lets log it if so.  */
-       if (!link) {
-               printk(KERN_WARNING
-                      "%s: Could not find address %d.%d.%d.%d\n",
-                      __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr));
+       if (unlikely(!link)) {
+               if (from_addr.sa.sa_family == AF_INET6) {
+                       printk(KERN_WARNING
+                              "%s association %p could not find address "
+                              "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+                              __FUNCTION__,
+                              asoc,
+                              NIP6(from_addr.v6.sin6_addr));
+               } else {
+                       printk(KERN_WARNING
+                              "%s association %p could not find address "
+                              "%u.%u.%u.%u\n",
+                              __FUNCTION__,
+                              asoc,
+                              NIPQUAD(from_addr.v4.sin_addr.s_addr));
+               }
                return SCTP_DISPOSITION_DISCARD;
        }
 
@@ -2095,9 +2109,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
        sctp_errhdr_t *err;
        struct sctp_chunk *reply;
        struct sctp_bind_addr *bp;
-       int attempts;
-
-       attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
+       int attempts = asoc->init_err_counter + 1;
 
        if (attempts >= asoc->max_init_attempts) {
                sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -2157,8 +2169,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
        /* Cast away the const modifier, as we want to just
         * rerun it through as a sideffect.
         */
-       sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,
-                       SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+       sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL());
 
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
@@ -2281,8 +2292,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
        if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
                error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
-       sctp_stop_t1_and_abort(commands, error);
-       return SCTP_DISPOSITION_ABORT;
+       return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport);
 }
 
 /*
@@ -2294,8 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep
                                        void *arg,
                                        sctp_cmd_seq_t *commands)
 {
-       sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR);
-       return SCTP_DISPOSITION_ABORT;
+       return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc,
+                                     (struct sctp_transport *)arg);
 }
 
 /*
@@ -2318,8 +2328,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
  *
  * This is common code called by several sctp_sf_*_abort() functions above.
  */
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
+sctp_disposition_t  sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+                                          __u16 error,
+                                          const struct sctp_association *asoc,
+                                          struct sctp_transport *transport)
 {
+       SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
                        SCTP_STATE(SCTP_STATE_CLOSED));
        SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -2328,6 +2342,7 @@ void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
        /* CMD_INIT_FAILED will DELETE_TCB. */
        sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
                        SCTP_U32(error));
+       return SCTP_DISPOSITION_ABORT;
 }
 
 /*
@@ -3805,6 +3820,10 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC,
                        SCTP_ASOC((struct sctp_association *) asoc));
 
+       /* Choose transport for INIT. */
+       sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+                       SCTP_CHUNK(repl));
+
        /* After sending the INIT, "A" starts the T1-init timer and
         * enters the COOKIE-WAIT state.
         */
@@ -4589,7 +4608,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
 }
 
 /*
- * sctp_sf_t1_timer_expire
+ * sctp_sf_t1_init_timer_expire
  *
  * Section: 4 Note: 2
  * Verification Tag:
@@ -4603,7 +4622,59 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
  *     endpoint MUST abort the initialization process and report the
  *     error to SCTP user.
  *
- *   3) If the T1-cookie timer expires, the endpoint MUST retransmit
+ * Outputs
+ * (timers, events)
+ *
+ */
+sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
+                                          const struct sctp_association *asoc,
+                                          const sctp_subtype_t type,
+                                          void *arg,
+                                          sctp_cmd_seq_t *commands)
+{
+       struct sctp_chunk *repl = NULL;
+       struct sctp_bind_addr *bp;
+       int attempts = asoc->init_err_counter + 1;
+
+       SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
+
+       if (attempts < asoc->max_init_attempts) {
+               bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
+               repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
+               if (!repl)
+                       return SCTP_DISPOSITION_NOMEM;
+
+               /* Choose transport for INIT. */
+               sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+                               SCTP_CHUNK(repl));
+
+               /* Issue a sideeffect to do the needed accounting. */
+               sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
+                               SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+       } else {
+               SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d"
+                                 " max_init_attempts: %d\n",
+                                 attempts, asoc->max_init_attempts);
+               sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
+                               SCTP_U32(SCTP_ERROR_NO_ERROR));
+               return SCTP_DISPOSITION_DELETE_TCB;
+       }
+
+       return SCTP_DISPOSITION_CONSUME;
+}
+
+/*
+ * sctp_sf_t1_cookie_timer_expire
+ *
+ * Section: 4 Note: 2
+ * Verification Tag:
+ * Inputs
+ * (endpoint, asoc)
+ *
+ *  RFC 2960 Section 4 Notes
+ *  3) If the T1-cookie timer expires, the endpoint MUST retransmit
  *     COOKIE ECHO and re-start the T1-cookie timer without changing
  *     state.  This MUST be repeated up to 'Max.Init.Retransmits' times.
  *     After that, the endpoint MUST abort the initialization process and
@@ -4613,46 +4684,26 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
  * (timers, events)
  *
  */
-sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep,
                                           const struct sctp_association *asoc,
                                           const sctp_subtype_t type,
                                           void *arg,
                                           sctp_cmd_seq_t *commands)
 {
-       struct sctp_chunk *repl;
-       struct sctp_bind_addr *bp;
-       sctp_event_timeout_t timer = (sctp_event_timeout_t) arg;
-       int timeout;
-       int attempts;
-
-       timeout = asoc->timeouts[timer];
-       attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
-       repl = NULL;
+       struct sctp_chunk *repl = NULL;
+       int attempts = asoc->init_err_counter + 1;
 
-       SCTP_DEBUG_PRINTK("Timer T1 expired.\n");
+       SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
 
        if (attempts < asoc->max_init_attempts) {
-               switch (timer) {
-               case SCTP_EVENT_TIMEOUT_T1_INIT:
-                       bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
-                       repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
-                       break;
-
-               case SCTP_EVENT_TIMEOUT_T1_COOKIE:
-                       repl = sctp_make_cookie_echo(asoc, NULL);
-                       break;
-
-               default:
-                       BUG();
-                       break;
-               };
-
+               repl = sctp_make_cookie_echo(asoc, NULL);
                if (!repl)
-                       goto nomem;
+                       return SCTP_DISPOSITION_NOMEM;
 
                /* Issue a sideeffect to do the needed accounting. */
-               sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
-                               SCTP_TO(timer));
+               sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART,
+                               SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
+
                sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
        } else {
                sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -4661,9 +4712,6 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep,
        }
 
        return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-       return SCTP_DISPOSITION_NOMEM;
 }
 
 /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN
index 8967846f69e888dde679ee864210658c85c6145b..75ef10408764247ec5999ad662dfc022a2660303 100644 (file)
@@ -783,7 +783,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_
        /* SCTP_STATE_COOKIE_WAIT */ \
        {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
        /* SCTP_STATE_COOKIE_ECHOED */ \
-       {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+       {.fn = sctp_sf_t1_cookie_timer_expire, \
+        .name = "sctp_sf_t1_cookie_timer_expire"}, \
        /* SCTP_STATE_ESTABLISHED */ \
        {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
        /* SCTP_STATE_SHUTDOWN_PENDING */ \
@@ -802,7 +803,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_
        /* SCTP_STATE_CLOSED */ \
        {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
        /* SCTP_STATE_COOKIE_WAIT */ \
-       {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+       {.fn = sctp_sf_t1_init_timer_expire, \
+        .name = "sctp_sf_t1_init_timer_expire"}, \
        /* SCTP_STATE_COOKIE_ECHOED */ \
        {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
        /* SCTP_STATE_ESTABLISHED */ \
index e6926cb1942078d1c3fa5d9eb15fc21dead93d33..aad55dc3792b39b1195e8cc3a0db7ea0176187ec 100644 (file)
@@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
  *             sockaddr_in6 [RFC 2553]),
  *   addr_len - the size of the address structure.
  */
-SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
 {
        int retval = 0;
 
        sctp_lock_sock(sk);
 
-       SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n",
-                         sk, uaddr, addr_len);
+       SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n",
+                         sk, addr, addr_len);
 
        /* Disallow binding twice. */
        if (!sctp_sk(sk)->ep->base.bind_addr.port)
-               retval = sctp_do_bind(sk, (union sctp_addr *)uaddr,
+               retval = sctp_do_bind(sk, (union sctp_addr *)addr,
                                      addr_len);
        else
                retval = -EINVAL;
@@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
        unsigned short snum;
        int ret = 0;
 
-       SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n",
-                         sk, addr, len);
-
        /* Common sockaddr verification. */
        af = sctp_sockaddr_af(sp, addr, len);
-       if (!af)
+       if (!af) {
+               SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n",
+                                 sk, addr, len);
                return -EINVAL;
+       }
+
+       snum = ntohs(addr->v4.sin_port);
+
+       SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ",
+                                ", port: %d, new port: %d, len: %d)\n",
+                                sk,
+                                addr,
+                                bp->port, snum,
+                                len);
 
        /* PF specific bind() address verification. */
        if (!sp->pf->bind_verify(sp, addr))
                return -EADDRNOTAVAIL;
 
-       snum= ntohs(addr->v4.sin_port);
-
-       SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n",
-                         bp->port, snum);
-
        /* We must either be unbound, or bind to the same port.  */
        if (bp->port && (snum != bp->port)) {
                SCTP_DEBUG_PRINTK("sctp_do_bind:"
@@ -816,7 +820,8 @@ out:
  *
  * Basically do nothing but copying the addresses from user to kernel
  * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
- * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace.
+ * This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
+ * from userspace.
  *
  * We don't use copy_from_user() for optimization: we first do the
  * sanity checks (buffer size -fast- and access check-healthy
@@ -913,6 +918,243 @@ out:
        return err;
 }
 
+/* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
+ *
+ * Common routine for handling connect() and sctp_connectx().
+ * Connect will come in with just a single address.
+ */
+static int __sctp_connect(struct sock* sk,
+                         struct sockaddr *kaddrs,
+                         int addrs_size)
+{
+       struct sctp_sock *sp;
+       struct sctp_endpoint *ep;
+       struct sctp_association *asoc = NULL;
+       struct sctp_association *asoc2;
+       struct sctp_transport *transport;
+       union sctp_addr to;
+       struct sctp_af *af;
+       sctp_scope_t scope;
+       long timeo;
+       int err = 0;
+       int addrcnt = 0;
+       int walk_size = 0;
+       struct sockaddr *sa_addr;
+       void *addr_buf;
+
+       sp = sctp_sk(sk);
+       ep = sp->ep;
+
+       /* connect() cannot be done on a socket that is already in ESTABLISHED
+        * state - UDP-style peeled off socket or a TCP-style socket that
+        * is already connected.
+        * It cannot be done even on a TCP-style listening socket.
+        */
+       if (sctp_sstate(sk, ESTABLISHED) ||
+           (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
+               err = -EISCONN;
+               goto out_free;
+       }
+
+       /* Walk through the addrs buffer and count the number of addresses. */
+       addr_buf = kaddrs;
+       while (walk_size < addrs_size) {
+               sa_addr = (struct sockaddr *)addr_buf;
+               af = sctp_get_af_specific(sa_addr->sa_family);
+
+               /* If the address family is not supported or if this address
+                * causes the address buffer to overflow return EINVAL.
+                */
+               if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
+                       err = -EINVAL;
+                       goto out_free;
+               }
+
+               err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr,
+                                      af->sockaddr_len);
+               if (err)
+                       goto out_free;
+
+               memcpy(&to, sa_addr, af->sockaddr_len);
+               to.v4.sin_port = ntohs(to.v4.sin_port);
+
+               /* Check if there already is a matching association on the
+                * endpoint (other than the one created here).
+                */
+               asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);
+               if (asoc2 && asoc2 != asoc) {
+                       if (asoc2->state >= SCTP_STATE_ESTABLISHED)
+                               err = -EISCONN;
+                       else
+                               err = -EALREADY;
+                       goto out_free;
+               }
+
+               /* If we could not find a matching association on the endpoint,
+                * make sure that there is no peeled-off association matching
+                * the peer address even on another socket.
+                */
+               if (sctp_endpoint_is_peeled_off(ep, &to)) {
+                       err = -EADDRNOTAVAIL;
+                       goto out_free;
+               }
+
+               if (!asoc) {
+                       /* If a bind() or sctp_bindx() is not called prior to
+                        * an sctp_connectx() call, the system picks an
+                        * ephemeral port and will choose an address set
+                        * equivalent to binding with a wildcard address.
+                        */
+                       if (!ep->base.bind_addr.port) {
+                               if (sctp_autobind(sk)) {
+                                       err = -EAGAIN;
+                                       goto out_free;
+                               }
+                       }
+
+                       scope = sctp_scope(&to);
+                       asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
+                       if (!asoc) {
+                               err = -ENOMEM;
+                               goto out_free;
+                       }
+               }
+
+               /* Prime the peer's transport structures.  */
+               transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,
+                                               SCTP_UNKNOWN);
+               if (!transport) {
+                       err = -ENOMEM;
+                       goto out_free;
+               }
+
+               addrcnt++;
+               addr_buf += af->sockaddr_len;
+               walk_size += af->sockaddr_len;
+       }
+
+       err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
+       if (err < 0) {
+               goto out_free;
+       }
+
+       err = sctp_primitive_ASSOCIATE(asoc, NULL);
+       if (err < 0) {
+               goto out_free;
+       }
+
+       /* Initialize sk's dport and daddr for getpeername() */
+       inet_sk(sk)->dport = htons(asoc->peer.port);
+       af = sctp_get_af_specific(to.sa.sa_family);
+       af->to_sk_daddr(&to, sk);
+
+       timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+       err = sctp_wait_for_connect(asoc, &timeo);
+
+       /* Don't free association on exit. */
+       asoc = NULL;
+
+out_free:
+
+       SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
+                         " kaddrs: %p err: %d\n",
+                         asoc, kaddrs, err);
+       if (asoc)
+               sctp_association_free(asoc);
+       return err;
+}
+
+/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
+ *
+ * API 8.9
+ * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
+ *
+ * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
+ * If the sd is an IPv6 socket, the addresses passed can either be IPv4
+ * or IPv6 addresses.
+ *
+ * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
+ * Section 3.1.2 for this usage.
+ *
+ * addrs is a pointer to an array of one or more socket addresses. Each
+ * address is contained in its appropriate structure (i.e. struct
+ * sockaddr_in or struct sockaddr_in6) the family of the address type
+ * must be used to distengish the address length (note that this
+ * representation is termed a "packed array" of addresses). The caller
+ * specifies the number of addresses in the array with addrcnt.
+ *
+ * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
+ * -1, and sets errno to the appropriate error code.
+ *
+ * For SCTP, the port given in each socket address must be the same, or
+ * sctp_connectx() will fail, setting errno to EINVAL.
+ *
+ * An application can use sctp_connectx to initiate an association with
+ * an endpoint that is multi-homed.  Much like sctp_bindx() this call
+ * allows a caller to specify multiple addresses at which a peer can be
+ * reached.  The way the SCTP stack uses the list of addresses to set up
+ * the association is implementation dependant.  This function only
+ * specifies that the stack will try to make use of all the addresses in
+ * the list when needed.
+ *
+ * Note that the list of addresses passed in is only used for setting up
+ * the association.  It does not necessarily equal the set of addresses
+ * the peer uses for the resulting association.  If the caller wants to
+ * find out the set of peer addresses, it must use sctp_getpaddrs() to
+ * retrieve them after the association has been set up.
+ *
+ * Basically do nothing but copying the addresses from user to kernel
+ * land and invoking either sctp_connectx(). This is used for tunneling
+ * the sctp_connectx() request through sctp_setsockopt() from userspace.
+ *
+ * We don't use copy_from_user() for optimization: we first do the
+ * sanity checks (buffer size -fast- and access check-healthy
+ * pointer); if all of those succeed, then we can alloc the memory
+ * (expensive operation) needed to copy the data to kernel. Then we do
+ * the copying without checking the user space area
+ * (__copy_from_user()).
+ *
+ * On exit there is no need to do sockfd_put(), sys_setsockopt() does
+ * it.
+ *
+ * sk        The sk of the socket
+ * addrs     The pointer to the addresses in user land
+ * addrssize Size of the addrs buffer
+ *
+ * Returns 0 if ok, <0 errno code on error.
+ */
+SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+                                     struct sockaddr __user *addrs,
+                                     int addrs_size)
+{
+       int err = 0;
+       struct sockaddr *kaddrs;
+
+       SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
+                         __FUNCTION__, sk, addrs, addrs_size);
+
+       if (unlikely(addrs_size <= 0))
+               return -EINVAL;
+
+       /* Check the user passed a healthy pointer.  */
+       if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size)))
+               return -EFAULT;
+
+       /* Alloc space for the address array in kernel memory.  */
+       kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
+       if (unlikely(!kaddrs))
+               return -ENOMEM;
+
+       if (__copy_from_user(kaddrs, addrs, addrs_size)) {
+               err = -EFAULT;
+       } else {
+               err = __sctp_connect(sk, kaddrs, addrs_size);
+       }
+
+       kfree(kaddrs);
+       return err;
+}
+
 /* API 3.1.4 close() - UDP Style Syntax
  * Applications use close() to perform graceful shutdown (as described in
  * Section 10.1 of [SCTP]) on ALL the associations currently represented
@@ -1095,7 +1337,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
        sp = sctp_sk(sk);
        ep = sp->ep;
 
-       SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name);
+       SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep);
 
        /* We cannot send a message over a TCP-style listening socket. */
        if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) {
@@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
                }
 
                /* Prime the peer's transport structures.  */
-               transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
+               transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN);
                if (!transport) {
                        err = -ENOMEM;
                        goto out_free;
@@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
                                               optlen, SCTP_BINDX_REM_ADDR);
                break;
 
+       case SCTP_SOCKOPT_CONNECTX:
+               /* 'optlen' is the size of the addresses buffer. */
+               retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval,
+                                              optlen);
+               break;
+
        case SCTP_DISABLE_FRAGMENTS:
                retval = sctp_setsockopt_disable_fragments(sk, optval, optlen);
                break;
@@ -2283,112 +2531,29 @@ out_nounlock:
  *
  * len: the size of the address.
  */
-SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
+SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
                             int addr_len)
 {
-       struct sctp_sock *sp;
-       struct sctp_endpoint *ep;
-       struct sctp_association *asoc;
-       struct sctp_transport *transport;
-       union sctp_addr to;
-       struct sctp_af *af;
-       sctp_scope_t scope;
-       long timeo;
        int err = 0;
+       struct sctp_af *af;
 
        sctp_lock_sock(sk);
 
-       SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n",
-                         __FUNCTION__, sk, uaddr, addr_len);
-
-       sp = sctp_sk(sk);
-       ep = sp->ep;
-
-       /* connect() cannot be done on a socket that is already in ESTABLISHED
-        * state - UDP-style peeled off socket or a TCP-style socket that
-        * is already connected.
-        * It cannot be done even on a TCP-style listening socket.
-        */
-       if (sctp_sstate(sk, ESTABLISHED) ||
-           (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
-               err = -EISCONN;
-               goto out_unlock;
-       }
-
-       err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len);
-       if (err)
-               goto out_unlock;
-
-       if (addr_len > sizeof(to))
-               addr_len = sizeof(to);
-       memcpy(&to, uaddr, addr_len);
-       to.v4.sin_port = ntohs(to.v4.sin_port);
-
-       asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
-       if (asoc) {
-               if (asoc->state >= SCTP_STATE_ESTABLISHED)
-                       err = -EISCONN;
-               else
-                       err = -EALREADY;
-               goto out_unlock;
-       }
-
-       /* If we could not find a matching association on the endpoint,
-        * make sure that there is no peeled-off association matching the
-        * peer address even on another socket.
-        */
-       if (sctp_endpoint_is_peeled_off(ep, &to)) {
-               err = -EADDRNOTAVAIL;
-               goto out_unlock;
-       }
-
-       /* If a bind() or sctp_bindx() is not called prior to a connect()
-        * call, the system picks an ephemeral port and will choose an address
-        * set equivalent to binding with a wildcard address.
-        */
-       if (!ep->base.bind_addr.port) {
-               if (sctp_autobind(sk)) {
-                       err = -EAGAIN;
-                       goto out_unlock;
-               }
-       }
-
-       scope = sctp_scope(&to);
-       asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
-       if (!asoc) {
-               err = -ENOMEM;
-               goto out_unlock;
-       }
+       SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
+                         __FUNCTION__, sk, addr, addr_len);
 
-       /* Prime the peer's transport structures.  */
-       transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
-       if (!transport) {
-               sctp_association_free(asoc);
-               goto out_unlock;
-       }
-       err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
-       if (err < 0) {
-               sctp_association_free(asoc);
-               goto out_unlock;
-       }
-
-       err = sctp_primitive_ASSOCIATE(asoc, NULL);
-       if (err < 0) {
-               sctp_association_free(asoc);
-               goto out_unlock;
+       /* Validate addr_len before calling common connect/connectx routine. */
+       af = sctp_get_af_specific(addr->sa_family);
+       if (!af || addr_len < af->sockaddr_len) {
+               err = -EINVAL;
+       } else {
+               /* Pass correct addr len to common routine (so it knows there
+                * is only one address being passed.
+                */
+               err = __sctp_connect(sk, addr, af->sockaddr_len);
        }
 
-       /* Initialize sk's dport and daddr for getpeername() */
-       inet_sk(sk)->dport = htons(asoc->peer.port);
-       af = sctp_get_af_specific(to.sa.sa_family);
-       af->to_sk_daddr(&to, sk);
-
-       timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
-       err = sctp_wait_for_connect(asoc, &timeo);
-
-out_unlock:
        sctp_release_sock(sk);
-
        return err;
 }
 
@@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
        /* Map ipv4 address into v4-mapped-on-v6 address.  */
        sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
                (union sctp_addr *)&status.sstat_primary.spinfo_address);
-       status.sstat_primary.spinfo_state = transport->active;
+       status.sstat_primary.spinfo_state = transport->state;
        status.sstat_primary.spinfo_cwnd = transport->cwnd;
        status.sstat_primary.spinfo_srtt = transport->srtt;
        status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
        status.sstat_primary.spinfo_mtu = transport->pmtu;
 
+       if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN)
+               status.sstat_primary.spinfo_state = SCTP_ACTIVE;
+
        if (put_user(len, optlen)) {
                retval = -EFAULT;
                goto out;
@@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
                return -EINVAL;
 
        pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
-       pinfo.spinfo_state = transport->active;
+       pinfo.spinfo_state = transport->state;
        pinfo.spinfo_cwnd = transport->cwnd;
        pinfo.spinfo_srtt = transport->srtt;
        pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
        pinfo.spinfo_mtu = transport->pmtu;
 
+       if (pinfo.spinfo_state == SCTP_UNKNOWN)
+               pinfo.spinfo_state = SCTP_ACTIVE;
+
        if (put_user(len, optlen)) {
                retval = -EFAULT;
                goto out;
@@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
        int retval = 0;
        int len;
 
-       SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk);
+       SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n",
+                         sk, optname);
 
        /* I can hardly begin to describe how wrong this is.  This is
         * so broken as to be worse than useless.  The API draft
@@ -4596,8 +4768,7 @@ out:
        return err;
 
 do_error:
-       if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
-                                               asoc->max_init_attempts)
+       if (asoc->init_err_counter + 1 >= asoc->max_init_attempts)
                err = -ETIMEDOUT;
        else
                err = -ECONNREFUSED;
index f30882e1e96acc3f99012b77a11d1238b39aa2f0..0ec0fde6e6c596d19727fa831dd61991fa4c7a47 100644 (file)
@@ -83,7 +83,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
        peer->last_time_used = jiffies;
        peer->last_time_ecne_reduced = jiffies;
 
-       peer->active = SCTP_ACTIVE;
+       peer->init_sent_count = 0;
+
+       peer->state = SCTP_ACTIVE;
        peer->hb_allowed = 0;
 
        /* Initialize the default path max_retrans.  */
index 0a4260719a123113b03e0e7bfed04ea363ca655f..d65ed8684fc1a340b1f470e3d3f50fc2b940a60f 100644 (file)
@@ -118,7 +118,6 @@ retry:
        xfrm_policy_put_afinfo(afinfo);
        return type;
 }
-EXPORT_SYMBOL(xfrm_get_type);
 
 int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
                    unsigned short family)
index 2537f26f097c8741aa19307e1a909ab1077a681d..9d206c282cf193a9867ff3b2c0078a683588a066 100644 (file)
@@ -1055,6 +1055,43 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 }
 
 EXPORT_SYMBOL(xfrm_state_mtu);
+
+int xfrm_init_state(struct xfrm_state *x)
+{
+       struct xfrm_state_afinfo *afinfo;
+       int family = x->props.family;
+       int err;
+
+       err = -EAFNOSUPPORT;
+       afinfo = xfrm_state_get_afinfo(family);
+       if (!afinfo)
+               goto error;
+
+       err = 0;
+       if (afinfo->init_flags)
+               err = afinfo->init_flags(x);
+
+       xfrm_state_put_afinfo(afinfo);
+
+       if (err)
+               goto error;
+
+       err = -EPROTONOSUPPORT;
+       x->type = xfrm_get_type(x->id.proto, family);
+       if (x->type == NULL)
+               goto error;
+
+       err = x->type->init_state(x);
+       if (err)
+               goto error;
+
+       x->km.state = XFRM_STATE_VALID;
+
+error:
+       return err;
+}
+
+EXPORT_SYMBOL(xfrm_init_state);
  
 void __init xfrm_state_init(void)
 {
index 5ce8558eac91f3543c3e924a2c3279e01fad4e61..ecade4893a139cc35d4fe345ce70242ede5358c4 100644 (file)
@@ -249,17 +249,10 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
        if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
                goto error;
 
-       err = -ENOENT;
-       x->type = xfrm_get_type(x->id.proto, x->props.family);
-       if (x->type == NULL)
-               goto error;
-
-       err = x->type->init_state(x, NULL);
+       err = xfrm_init_state(x);
        if (err)
                goto error;
 
-       x->curlft.add_time = (unsigned long) xtime.tv_sec;
-       x->km.state = XFRM_STATE_VALID;
        x->km.seq = p->seq;
 
        return x;