diff options
100 files changed, 2562 insertions, 829 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 475950c8a831..ee8a9ad7bbd9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -67,10 +67,6 @@ config GENERIC_BUST_SPINLOCK | |||
67 | config GENERIC_ISA_DMA | 67 | config GENERIC_ISA_DMA |
68 | bool | 68 | bool |
69 | 69 | ||
70 | config GENERIC_IOMAP | ||
71 | bool | ||
72 | default y | ||
73 | |||
74 | config FIQ | 70 | config FIQ |
75 | bool | 71 | bool |
76 | 72 | ||
@@ -202,6 +198,11 @@ config ARCH_H720X | |||
202 | help | 198 | help |
203 | This enables support for systems based on the Hynix HMS720x | 199 | This enables support for systems based on the Hynix HMS720x |
204 | 200 | ||
201 | config ARCH_AAEC2000 | ||
202 | bool "Agilent AAEC-2000 based" | ||
203 | help | ||
204 | This enables support for systems based on the Agilent AAEC-2000 | ||
205 | |||
205 | endchoice | 206 | endchoice |
206 | 207 | ||
207 | source "arch/arm/mach-clps711x/Kconfig" | 208 | source "arch/arm/mach-clps711x/Kconfig" |
@@ -234,6 +235,8 @@ source "arch/arm/mach-h720x/Kconfig" | |||
234 | 235 | ||
235 | source "arch/arm/mach-versatile/Kconfig" | 236 | source "arch/arm/mach-versatile/Kconfig" |
236 | 237 | ||
238 | source "arch/arm/mach-aaec2000/Kconfig" | ||
239 | |||
237 | # Definitions to make life easier | 240 | # Definitions to make life easier |
238 | config ARCH_ACORN | 241 | config ARCH_ACORN |
239 | bool | 242 | bool |
@@ -277,7 +280,7 @@ config ISA_DMA_API | |||
277 | default y | 280 | default y |
278 | 281 | ||
279 | config PCI | 282 | config PCI |
280 | bool "PCI support" if ARCH_INTEGRATOR_AP | 283 | bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB |
281 | help | 284 | help |
282 | Find out whether you have a PCI motherboard. PCI is the name of a | 285 | Find out whether you have a PCI motherboard. PCI is the name of a |
283 | bus system, i.e. the way the CPU talks to the other stuff inside | 286 | bus system, i.e. the way the CPU talks to the other stuff inside |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 2277e3d179cc..8330495e2448 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -97,6 +97,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 | |||
97 | machine-$(CONFIG_ARCH_VERSATILE) := versatile | 97 | machine-$(CONFIG_ARCH_VERSATILE) := versatile |
98 | machine-$(CONFIG_ARCH_IMX) := imx | 98 | machine-$(CONFIG_ARCH_IMX) := imx |
99 | machine-$(CONFIG_ARCH_H720X) := h720x | 99 | machine-$(CONFIG_ARCH_H720X) := h720x |
100 | machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 | ||
100 | 101 | ||
101 | ifeq ($(CONFIG_ARCH_EBSA110),y) | 102 | ifeq ($(CONFIG_ARCH_EBSA110),y) |
102 | # This is what happens if you forget the IOCS16 line. | 103 | # This is what happens if you forget the IOCS16 line. |
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 5797b1b100a1..9d63a01214eb 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/dmapool.h> | 30 | #include <linux/dmapool.h> |
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | 32 | ||
33 | #include <asm/cacheflush.h> | ||
34 | |||
33 | #undef DEBUG | 35 | #undef DEBUG |
34 | 36 | ||
35 | #undef STATS | 37 | #undef STATS |
@@ -302,12 +304,24 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
302 | 304 | ||
303 | DO_STATS ( device_info->bounce_count++ ); | 305 | DO_STATS ( device_info->bounce_count++ ); |
304 | 306 | ||
305 | if ((dir == DMA_FROM_DEVICE) || | 307 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) { |
306 | (dir == DMA_BIDIRECTIONAL)) { | 308 | unsigned long ptr; |
309 | |||
307 | dev_dbg(dev, | 310 | dev_dbg(dev, |
308 | "%s: copy back safe %p to unsafe %p size %d\n", | 311 | "%s: copy back safe %p to unsafe %p size %d\n", |
309 | __func__, buf->safe, buf->ptr, size); | 312 | __func__, buf->safe, buf->ptr, size); |
310 | memcpy(buf->ptr, buf->safe, size); | 313 | memcpy(buf->ptr, buf->safe, size); |
314 | |||
315 | /* | ||
316 | * DMA buffers must have the same cache properties | ||
317 | * as if they were really used for DMA - which means | ||
318 | * data must be written back to RAM. Note that | ||
319 | * we don't use dmac_flush_range() here for the | ||
320 | * bidirectional case because we know the cache | ||
321 | * lines will be coherent with the data written. | ||
322 | */ | ||
323 | ptr = (unsigned long)buf->ptr; | ||
324 | dmac_clean_range(ptr, ptr + size); | ||
311 | } | 325 | } |
312 | free_safe_buffer(device_info, buf); | 326 | free_safe_buffer(device_info, buf); |
313 | } | 327 | } |
diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c index c2c557a224c2..c94864c5b1af 100644 --- a/arch/arm/common/sharpsl_param.c +++ b/arch/arm/common/sharpsl_param.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * them early in the boot process, then pass them to the appropriate drivers. | 22 | * them early in the boot process, then pass them to the appropriate drivers. |
23 | * Not all devices use all paramaters but the format is common to all. | 23 | * Not all devices use all paramaters but the format is common to all. |
24 | */ | 24 | */ |
25 | #ifdef ARCH_SA1100 | 25 | #ifdef CONFIG_ARCH_SA1100 |
26 | #define PARAM_BASE 0xe8ffc000 | 26 | #define PARAM_BASE 0xe8ffc000 |
27 | #else | 27 | #else |
28 | #define PARAM_BASE 0xa0000a00 | 28 | #define PARAM_BASE 0xa0000a00 |
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig index e8f9fccffe84..06fae4b62774 100644 --- a/arch/arm/configs/enp2611_defconfig +++ b/arch/arm/configs/enp2611_defconfig | |||
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0 | |||
50 | # | 50 | # |
51 | # Loadable module support | 51 | # Loadable module support |
52 | # | 52 | # |
53 | # CONFIG_MODULES is not set | 53 | CONFIG_MODULES=y |
54 | CONFIG_MODULE_UNLOAD=y | ||
55 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
56 | CONFIG_OBSOLETE_MODPARM=y | ||
57 | # CONFIG_MODVERSIONS is not set | ||
58 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
59 | CONFIG_KMOD=y | ||
54 | 60 | ||
55 | # | 61 | # |
56 | # System Type | 62 | # System Type |
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index 4fd663ecbe39..810a450a55d2 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig | |||
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0 | |||
50 | # | 50 | # |
51 | # Loadable module support | 51 | # Loadable module support |
52 | # | 52 | # |
53 | # CONFIG_MODULES is not set | 53 | CONFIG_MODULES=y |
54 | CONFIG_MODULE_UNLOAD=y | ||
55 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
56 | CONFIG_OBSOLETE_MODPARM=y | ||
57 | # CONFIG_MODVERSIONS is not set | ||
58 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
59 | CONFIG_KMOD=y | ||
54 | 60 | ||
55 | # | 61 | # |
56 | # System Type | 62 | # System Type |
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig index 6f51c98084a3..72e1b940e975 100644 --- a/arch/arm/configs/ixdp2401_defconfig +++ b/arch/arm/configs/ixdp2401_defconfig | |||
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0 | |||
50 | # | 50 | # |
51 | # Loadable module support | 51 | # Loadable module support |
52 | # | 52 | # |
53 | # CONFIG_MODULES is not set | 53 | CONFIG_MODULES=y |
54 | CONFIG_MODULE_UNLOAD=y | ||
55 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
56 | CONFIG_OBSOLETE_MODPARM=y | ||
57 | # CONFIG_MODVERSIONS is not set | ||
58 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
59 | CONFIG_KMOD=y | ||
54 | 60 | ||
55 | # | 61 | # |
56 | # System Type | 62 | # System Type |
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig index 7be3521f91fc..1592e45f0278 100644 --- a/arch/arm/configs/ixdp2800_defconfig +++ b/arch/arm/configs/ixdp2800_defconfig | |||
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0 | |||
50 | # | 50 | # |
51 | # Loadable module support | 51 | # Loadable module support |
52 | # | 52 | # |
53 | # CONFIG_MODULES is not set | 53 | CONFIG_MODULES=y |
54 | CONFIG_MODULE_UNLOAD=y | ||
55 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
56 | CONFIG_OBSOLETE_MODPARM=y | ||
57 | # CONFIG_MODVERSIONS is not set | ||
58 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
59 | CONFIG_KMOD=y | ||
54 | 60 | ||
55 | # | 61 | # |
56 | # System Type | 62 | # System Type |
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig index cd84a20f30f1..f1afe3d09ec6 100644 --- a/arch/arm/configs/ixdp2801_defconfig +++ b/arch/arm/configs/ixdp2801_defconfig | |||
@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0 | |||
50 | # | 50 | # |
51 | # Loadable module support | 51 | # Loadable module support |
52 | # | 52 | # |
53 | # CONFIG_MODULES is not set | 53 | CONFIG_MODULES=y |
54 | CONFIG_MODULE_UNLOAD=y | ||
55 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
56 | CONFIG_OBSOLETE_MODPARM=y | ||
57 | # CONFIG_MODVERSIONS is not set | ||
58 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
59 | CONFIG_KMOD=y | ||
54 | 60 | ||
55 | # | 61 | # |
56 | # System Type | 62 | # System Type |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 4a2af55e134b..3e1b0327e4d7 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -6,7 +6,7 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) | |||
6 | 6 | ||
7 | # Object file lists. | 7 | # Object file lists. |
8 | 8 | ||
9 | obj-y := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o \ | 9 | obj-y := compat.o dma.o entry-armv.o entry-common.o irq.o \ |
10 | process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \ | 10 | process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \ |
11 | time.o traps.o | 11 | time.o traps.o |
12 | 12 | ||
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c deleted file mode 100644 index 4e02fbeb10a6..000000000000 --- a/arch/arm/kernel/arch.c +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/arch.c | ||
3 | * | ||
4 | * Architecture specific fixups. | ||
5 | */ | ||
6 | #include <linux/config.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/types.h> | ||
9 | |||
10 | #include <asm/elf.h> | ||
11 | #include <asm/page.h> | ||
12 | #include <asm/setup.h> | ||
13 | #include <asm/mach/arch.h> | ||
14 | |||
15 | unsigned int vram_size; | ||
16 | |||
17 | #ifdef CONFIG_ARCH_ACORN | ||
18 | |||
19 | unsigned int memc_ctrl_reg; | ||
20 | unsigned int number_mfm_drives; | ||
21 | |||
22 | static int __init parse_tag_acorn(const struct tag *tag) | ||
23 | { | ||
24 | memc_ctrl_reg = tag->u.acorn.memc_control_reg; | ||
25 | number_mfm_drives = tag->u.acorn.adfsdrives; | ||
26 | |||
27 | switch (tag->u.acorn.vram_pages) { | ||
28 | case 512: | ||
29 | vram_size += PAGE_SIZE * 256; | ||
30 | case 256: | ||
31 | vram_size += PAGE_SIZE * 256; | ||
32 | default: | ||
33 | break; | ||
34 | } | ||
35 | #if 0 | ||
36 | if (vram_size) { | ||
37 | desc->video_start = 0x02000000; | ||
38 | desc->video_end = 0x02000000 + vram_size; | ||
39 | } | ||
40 | #endif | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | __tagtable(ATAG_ACORN, parse_tag_acorn); | ||
45 | |||
46 | #endif | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 45ed036336e0..34892758f098 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -145,7 +145,8 @@ int __init __cpu_up(unsigned int cpu) | |||
145 | pgd_free(pgd); | 145 | pgd_free(pgd); |
146 | 146 | ||
147 | if (ret) { | 147 | if (ret) { |
148 | printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu); | 148 | printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu); |
149 | |||
149 | /* | 150 | /* |
150 | * FIXME: We need to clean up the new idle thread. --rmk | 151 | * FIXME: We need to clean up the new idle thread. --rmk |
151 | */ | 152 | */ |
diff --git a/arch/arm/lib/ashldi3.c b/arch/arm/lib/ashldi3.c index 130f5a839669..b62875cfd8f8 100644 --- a/arch/arm/lib/ashldi3.c +++ b/arch/arm/lib/ashldi3.c | |||
@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */ | |||
31 | 31 | ||
32 | #include "gcclib.h" | 32 | #include "gcclib.h" |
33 | 33 | ||
34 | DItype | 34 | s64 __ashldi3(s64 u, int b) |
35 | __ashldi3 (DItype u, word_type b) | ||
36 | { | 35 | { |
37 | DIunion w; | 36 | DIunion w; |
38 | word_type bm; | 37 | int bm; |
39 | DIunion uu; | 38 | DIunion uu; |
40 | 39 | ||
41 | if (b == 0) | 40 | if (b == 0) |
42 | return u; | 41 | return u; |
43 | 42 | ||
44 | uu.ll = u; | 43 | uu.ll = u; |
45 | 44 | ||
46 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; | 45 | bm = (sizeof(s32) * BITS_PER_UNIT) - b; |
47 | if (bm <= 0) | 46 | if (bm <= 0) { |
48 | { | 47 | w.s.low = 0; |
49 | w.s.low = 0; | 48 | w.s.high = (u32) uu.s.low << -bm; |
50 | w.s.high = (USItype)uu.s.low << -bm; | 49 | } else { |
51 | } | 50 | u32 carries = (u32) uu.s.low >> bm; |
52 | else | 51 | w.s.low = (u32) uu.s.low << b; |
53 | { | 52 | w.s.high = ((u32) uu.s.high << b) | carries; |
54 | USItype carries = (USItype)uu.s.low >> bm; | 53 | } |
55 | w.s.low = (USItype)uu.s.low << b; | 54 | |
56 | w.s.high = ((USItype)uu.s.high << b) | carries; | 55 | return w.ll; |
57 | } | ||
58 | |||
59 | return w.ll; | ||
60 | } | 56 | } |
61 | |||
diff --git a/arch/arm/lib/ashrdi3.c b/arch/arm/lib/ashrdi3.c index 71625d218f8d..9a8600a7543f 100644 --- a/arch/arm/lib/ashrdi3.c +++ b/arch/arm/lib/ashrdi3.c | |||
@@ -31,31 +31,27 @@ Boston, MA 02111-1307, USA. */ | |||
31 | 31 | ||
32 | #include "gcclib.h" | 32 | #include "gcclib.h" |
33 | 33 | ||
34 | DItype | 34 | s64 __ashrdi3(s64 u, int b) |
35 | __ashrdi3 (DItype u, word_type b) | ||
36 | { | 35 | { |
37 | DIunion w; | 36 | DIunion w; |
38 | word_type bm; | 37 | int bm; |
39 | DIunion uu; | 38 | DIunion uu; |
40 | 39 | ||
41 | if (b == 0) | 40 | if (b == 0) |
42 | return u; | 41 | return u; |
43 | 42 | ||
44 | uu.ll = u; | 43 | uu.ll = u; |
45 | 44 | ||
46 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; | 45 | bm = (sizeof(s32) * BITS_PER_UNIT) - b; |
47 | if (bm <= 0) | 46 | if (bm <= 0) { |
48 | { | 47 | /* w.s.high = 1..1 or 0..0 */ |
49 | /* w.s.high = 1..1 or 0..0 */ | 48 | w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1); |
50 | w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); | 49 | w.s.low = uu.s.high >> -bm; |
51 | w.s.low = uu.s.high >> -bm; | 50 | } else { |
52 | } | 51 | u32 carries = (u32) uu.s.high << bm; |
53 | else | 52 | w.s.high = uu.s.high >> b; |
54 | { | 53 | w.s.low = ((u32) uu.s.low >> b) | carries; |
55 | USItype carries = (USItype)uu.s.high << bm; | 54 | } |
56 | w.s.high = uu.s.high >> b; | 55 | |
57 | w.s.low = ((USItype)uu.s.low >> b) | carries; | 56 | return w.ll; |
58 | } | ||
59 | |||
60 | return w.ll; | ||
61 | } | 57 | } |
diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h index 65314a3d9e27..8b6dcc656de7 100644 --- a/arch/arm/lib/gcclib.h +++ b/arch/arm/lib/gcclib.h | |||
@@ -1,25 +1,22 @@ | |||
1 | /* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */ | 1 | /* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */ |
2 | /* I Molton 29/07/01 */ | 2 | /* I Molton 29/07/01 */ |
3 | 3 | ||
4 | #define BITS_PER_UNIT 8 | 4 | #include <linux/types.h> |
5 | #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT) | ||
6 | 5 | ||
7 | typedef unsigned int UQItype __attribute__ ((mode (QI))); | 6 | #define BITS_PER_UNIT 8 |
8 | typedef int SItype __attribute__ ((mode (SI))); | 7 | #define SI_TYPE_SIZE (sizeof(s32) * BITS_PER_UNIT) |
9 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
10 | typedef int DItype __attribute__ ((mode (DI))); | ||
11 | typedef int word_type __attribute__ ((mode (__word__))); | ||
12 | typedef unsigned int UDItype __attribute__ ((mode (DI))); | ||
13 | 8 | ||
14 | #ifdef __ARMEB__ | 9 | #ifdef __ARMEB__ |
15 | struct DIstruct {SItype high, low;}; | 10 | struct DIstruct { |
11 | s32 high, low; | ||
12 | }; | ||
16 | #else | 13 | #else |
17 | struct DIstruct {SItype low, high;}; | 14 | struct DIstruct { |
15 | s32 low, high; | ||
16 | }; | ||
18 | #endif | 17 | #endif |
19 | 18 | ||
20 | typedef union | 19 | typedef union { |
21 | { | 20 | struct DIstruct s; |
22 | struct DIstruct s; | 21 | s64 ll; |
23 | DItype ll; | ||
24 | } DIunion; | 22 | } DIunion; |
25 | |||
diff --git a/arch/arm/lib/longlong.h b/arch/arm/lib/longlong.h index 179eea4edc35..90ae647e4d76 100644 --- a/arch/arm/lib/longlong.h +++ b/arch/arm/lib/longlong.h | |||
@@ -26,18 +26,18 @@ | |||
26 | 26 | ||
27 | #define __BITS4 (SI_TYPE_SIZE / 4) | 27 | #define __BITS4 (SI_TYPE_SIZE / 4) |
28 | #define __ll_B (1L << (SI_TYPE_SIZE / 2)) | 28 | #define __ll_B (1L << (SI_TYPE_SIZE / 2)) |
29 | #define __ll_lowpart(t) ((USItype) (t) % __ll_B) | 29 | #define __ll_lowpart(t) ((u32) (t) % __ll_B) |
30 | #define __ll_highpart(t) ((USItype) (t) / __ll_B) | 30 | #define __ll_highpart(t) ((u32) (t) / __ll_B) |
31 | 31 | ||
32 | /* Define auxiliary asm macros. | 32 | /* Define auxiliary asm macros. |
33 | 33 | ||
34 | 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) | 34 | 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) |
35 | multiplies two USItype integers MULTIPLER and MULTIPLICAND, | 35 | multiplies two u32 integers MULTIPLER and MULTIPLICAND, |
36 | and generates a two-part USItype product in HIGH_PROD and | 36 | and generates a two-part u32 product in HIGH_PROD and |
37 | LOW_PROD. | 37 | LOW_PROD. |
38 | 38 | ||
39 | 2) __umulsidi3(a,b) multiplies two USItype integers A and B, | 39 | 2) __umulsidi3(a,b) multiplies two u32 integers A and B, |
40 | and returns a UDItype product. This is just a variant of umul_ppmm. | 40 | and returns a u64 product. This is just a variant of umul_ppmm. |
41 | 41 | ||
42 | 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, | 42 | 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, |
43 | denominator) divides a two-word unsigned integer, composed by the | 43 | denominator) divides a two-word unsigned integer, composed by the |
@@ -77,23 +77,23 @@ | |||
77 | #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ | 77 | #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ |
78 | __asm__ ("adds %1, %4, %5 \n\ | 78 | __asm__ ("adds %1, %4, %5 \n\ |
79 | adc %0, %2, %3" \ | 79 | adc %0, %2, %3" \ |
80 | : "=r" ((USItype) (sh)), \ | 80 | : "=r" ((u32) (sh)), \ |
81 | "=&r" ((USItype) (sl)) \ | 81 | "=&r" ((u32) (sl)) \ |
82 | : "%r" ((USItype) (ah)), \ | 82 | : "%r" ((u32) (ah)), \ |
83 | "rI" ((USItype) (bh)), \ | 83 | "rI" ((u32) (bh)), \ |
84 | "%r" ((USItype) (al)), \ | 84 | "%r" ((u32) (al)), \ |
85 | "rI" ((USItype) (bl))) | 85 | "rI" ((u32) (bl))) |
86 | #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ | 86 | #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ |
87 | __asm__ ("subs %1, %4, %5 \n\ | 87 | __asm__ ("subs %1, %4, %5 \n\ |
88 | sbc %0, %2, %3" \ | 88 | sbc %0, %2, %3" \ |
89 | : "=r" ((USItype) (sh)), \ | 89 | : "=r" ((u32) (sh)), \ |
90 | "=&r" ((USItype) (sl)) \ | 90 | "=&r" ((u32) (sl)) \ |
91 | : "r" ((USItype) (ah)), \ | 91 | : "r" ((u32) (ah)), \ |
92 | "rI" ((USItype) (bh)), \ | 92 | "rI" ((u32) (bh)), \ |
93 | "r" ((USItype) (al)), \ | 93 | "r" ((u32) (al)), \ |
94 | "rI" ((USItype) (bl))) | 94 | "rI" ((u32) (bl))) |
95 | #define umul_ppmm(xh, xl, a, b) \ | 95 | #define umul_ppmm(xh, xl, a, b) \ |
96 | {register USItype __t0, __t1, __t2; \ | 96 | {register u32 __t0, __t1, __t2; \ |
97 | __asm__ ("%@ Inlined umul_ppmm \n\ | 97 | __asm__ ("%@ Inlined umul_ppmm \n\ |
98 | mov %2, %5, lsr #16 \n\ | 98 | mov %2, %5, lsr #16 \n\ |
99 | mov %0, %6, lsr #16 \n\ | 99 | mov %0, %6, lsr #16 \n\ |
@@ -107,14 +107,14 @@ | |||
107 | addcs %0, %0, #65536 \n\ | 107 | addcs %0, %0, #65536 \n\ |
108 | adds %1, %1, %3, lsl #16 \n\ | 108 | adds %1, %1, %3, lsl #16 \n\ |
109 | adc %0, %0, %3, lsr #16" \ | 109 | adc %0, %0, %3, lsr #16" \ |
110 | : "=&r" ((USItype) (xh)), \ | 110 | : "=&r" ((u32) (xh)), \ |
111 | "=r" ((USItype) (xl)), \ | 111 | "=r" ((u32) (xl)), \ |
112 | "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ | 112 | "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ |
113 | : "r" ((USItype) (a)), \ | 113 | : "r" ((u32) (a)), \ |
114 | "r" ((USItype) (b)));} | 114 | "r" ((u32) (b)));} |
115 | #define UMUL_TIME 20 | 115 | #define UMUL_TIME 20 |
116 | #define UDIV_TIME 100 | 116 | #define UDIV_TIME 100 |
117 | #endif /* __arm__ */ | 117 | #endif /* __arm__ */ |
118 | 118 | ||
119 | #define __umulsidi3(u, v) \ | 119 | #define __umulsidi3(u, v) \ |
120 | ({DIunion __w; \ | 120 | ({DIunion __w; \ |
@@ -123,14 +123,14 @@ | |||
123 | 123 | ||
124 | #define __udiv_qrnnd_c(q, r, n1, n0, d) \ | 124 | #define __udiv_qrnnd_c(q, r, n1, n0, d) \ |
125 | do { \ | 125 | do { \ |
126 | USItype __d1, __d0, __q1, __q0; \ | 126 | u32 __d1, __d0, __q1, __q0; \ |
127 | USItype __r1, __r0, __m; \ | 127 | u32 __r1, __r0, __m; \ |
128 | __d1 = __ll_highpart (d); \ | 128 | __d1 = __ll_highpart (d); \ |
129 | __d0 = __ll_lowpart (d); \ | 129 | __d0 = __ll_lowpart (d); \ |
130 | \ | 130 | \ |
131 | __r1 = (n1) % __d1; \ | 131 | __r1 = (n1) % __d1; \ |
132 | __q1 = (n1) / __d1; \ | 132 | __q1 = (n1) / __d1; \ |
133 | __m = (USItype) __q1 * __d0; \ | 133 | __m = (u32) __q1 * __d0; \ |
134 | __r1 = __r1 * __ll_B | __ll_highpart (n0); \ | 134 | __r1 = __r1 * __ll_B | __ll_highpart (n0); \ |
135 | if (__r1 < __m) \ | 135 | if (__r1 < __m) \ |
136 | { \ | 136 | { \ |
@@ -143,7 +143,7 @@ | |||
143 | \ | 143 | \ |
144 | __r0 = __r1 % __d1; \ | 144 | __r0 = __r1 % __d1; \ |
145 | __q0 = __r1 / __d1; \ | 145 | __q0 = __r1 / __d1; \ |
146 | __m = (USItype) __q0 * __d0; \ | 146 | __m = (u32) __q0 * __d0; \ |
147 | __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ | 147 | __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ |
148 | if (__r0 < __m) \ | 148 | if (__r0 < __m) \ |
149 | { \ | 149 | { \ |
@@ -154,7 +154,7 @@ | |||
154 | } \ | 154 | } \ |
155 | __r0 -= __m; \ | 155 | __r0 -= __m; \ |
156 | \ | 156 | \ |
157 | (q) = (USItype) __q1 * __ll_B | __q0; \ | 157 | (q) = (u32) __q1 * __ll_B | __q0; \ |
158 | (r) = __r0; \ | 158 | (r) = __r0; \ |
159 | } while (0) | 159 | } while (0) |
160 | 160 | ||
@@ -163,14 +163,14 @@ | |||
163 | 163 | ||
164 | #define count_leading_zeros(count, x) \ | 164 | #define count_leading_zeros(count, x) \ |
165 | do { \ | 165 | do { \ |
166 | USItype __xr = (x); \ | 166 | u32 __xr = (x); \ |
167 | USItype __a; \ | 167 | u32 __a; \ |
168 | \ | 168 | \ |
169 | if (SI_TYPE_SIZE <= 32) \ | 169 | if (SI_TYPE_SIZE <= 32) \ |
170 | { \ | 170 | { \ |
171 | __a = __xr < ((USItype)1<<2*__BITS4) \ | 171 | __a = __xr < ((u32)1<<2*__BITS4) \ |
172 | ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \ | 172 | ? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4) \ |
173 | : (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ | 173 | : (__xr < ((u32)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ |
174 | } \ | 174 | } \ |
175 | else \ | 175 | else \ |
176 | { \ | 176 | { \ |
diff --git a/arch/arm/lib/lshrdi3.c b/arch/arm/lib/lshrdi3.c index b666f1bad451..3681f49d2b6e 100644 --- a/arch/arm/lib/lshrdi3.c +++ b/arch/arm/lib/lshrdi3.c | |||
@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */ | |||
31 | 31 | ||
32 | #include "gcclib.h" | 32 | #include "gcclib.h" |
33 | 33 | ||
34 | DItype | 34 | s64 __lshrdi3(s64 u, int b) |
35 | __lshrdi3 (DItype u, word_type b) | ||
36 | { | 35 | { |
37 | DIunion w; | 36 | DIunion w; |
38 | word_type bm; | 37 | int bm; |
39 | DIunion uu; | 38 | DIunion uu; |
40 | 39 | ||
41 | if (b == 0) | 40 | if (b == 0) |
42 | return u; | 41 | return u; |
43 | 42 | ||
44 | uu.ll = u; | 43 | uu.ll = u; |
45 | 44 | ||
46 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; | 45 | bm = (sizeof(s32) * BITS_PER_UNIT) - b; |
47 | if (bm <= 0) | 46 | if (bm <= 0) { |
48 | { | 47 | w.s.high = 0; |
49 | w.s.high = 0; | 48 | w.s.low = (u32) uu.s.high >> -bm; |
50 | w.s.low = (USItype)uu.s.high >> -bm; | 49 | } else { |
51 | } | 50 | u32 carries = (u32) uu.s.high << bm; |
52 | else | 51 | w.s.high = (u32) uu.s.high >> b; |
53 | { | 52 | w.s.low = ((u32) uu.s.low >> b) | carries; |
54 | USItype carries = (USItype)uu.s.high << bm; | 53 | } |
55 | w.s.high = (USItype)uu.s.high >> b; | 54 | |
56 | w.s.low = ((USItype)uu.s.low >> b) | carries; | 55 | return w.ll; |
57 | } | ||
58 | |||
59 | return w.ll; | ||
60 | } | 56 | } |
61 | |||
diff --git a/arch/arm/lib/muldi3.c b/arch/arm/lib/muldi3.c index 44d611b1cfdb..0a3b93313f18 100644 --- a/arch/arm/lib/muldi3.c +++ b/arch/arm/lib/muldi3.c | |||
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */ | |||
32 | #include "gcclib.h" | 32 | #include "gcclib.h" |
33 | 33 | ||
34 | #define umul_ppmm(xh, xl, a, b) \ | 34 | #define umul_ppmm(xh, xl, a, b) \ |
35 | {register USItype __t0, __t1, __t2; \ | 35 | {register u32 __t0, __t1, __t2; \ |
36 | __asm__ ("%@ Inlined umul_ppmm \n\ | 36 | __asm__ ("%@ Inlined umul_ppmm \n\ |
37 | mov %2, %5, lsr #16 \n\ | 37 | mov %2, %5, lsr #16 \n\ |
38 | mov %0, %6, lsr #16 \n\ | 38 | mov %0, %6, lsr #16 \n\ |
@@ -46,32 +46,27 @@ Boston, MA 02111-1307, USA. */ | |||
46 | addcs %0, %0, #65536 \n\ | 46 | addcs %0, %0, #65536 \n\ |
47 | adds %1, %1, %3, lsl #16 \n\ | 47 | adds %1, %1, %3, lsl #16 \n\ |
48 | adc %0, %0, %3, lsr #16" \ | 48 | adc %0, %0, %3, lsr #16" \ |
49 | : "=&r" ((USItype) (xh)), \ | 49 | : "=&r" ((u32) (xh)), \ |
50 | "=r" ((USItype) (xl)), \ | 50 | "=r" ((u32) (xl)), \ |
51 | "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ | 51 | "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ |
52 | : "r" ((USItype) (a)), \ | 52 | : "r" ((u32) (a)), \ |
53 | "r" ((USItype) (b)));} | 53 | "r" ((u32) (b)));} |
54 | |||
55 | 54 | ||
56 | #define __umulsidi3(u, v) \ | 55 | #define __umulsidi3(u, v) \ |
57 | ({DIunion __w; \ | 56 | ({DIunion __w; \ |
58 | umul_ppmm (__w.s.high, __w.s.low, u, v); \ | 57 | umul_ppmm (__w.s.high, __w.s.low, u, v); \ |
59 | __w.ll; }) | 58 | __w.ll; }) |
60 | 59 | ||
61 | 60 | s64 __muldi3(s64 u, s64 v) | |
62 | DItype | ||
63 | __muldi3 (DItype u, DItype v) | ||
64 | { | 61 | { |
65 | DIunion w; | 62 | DIunion w; |
66 | DIunion uu, vv; | 63 | DIunion uu, vv; |
67 | 64 | ||
68 | uu.ll = u, | 65 | uu.ll = u, vv.ll = v; |
69 | vv.ll = v; | ||
70 | 66 | ||
71 | w.ll = __umulsidi3 (uu.s.low, vv.s.low); | 67 | w.ll = __umulsidi3(uu.s.low, vv.s.low); |
72 | w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high | 68 | w.s.high += ((u32) uu.s.low * (u32) vv.s.high |
73 | + (USItype) uu.s.high * (USItype) vv.s.low); | 69 | + (u32) uu.s.high * (u32) vv.s.low); |
74 | 70 | ||
75 | return w.ll; | 71 | return w.ll; |
76 | } | 72 | } |
77 | |||
diff --git a/arch/arm/lib/ucmpdi2.c b/arch/arm/lib/ucmpdi2.c index 6c6ae63efa02..57f3f2df3850 100644 --- a/arch/arm/lib/ucmpdi2.c +++ b/arch/arm/lib/ucmpdi2.c | |||
@@ -31,21 +31,19 @@ Boston, MA 02111-1307, USA. */ | |||
31 | 31 | ||
32 | #include "gcclib.h" | 32 | #include "gcclib.h" |
33 | 33 | ||
34 | word_type | 34 | int __ucmpdi2(s64 a, s64 b) |
35 | __ucmpdi2 (DItype a, DItype b) | ||
36 | { | 35 | { |
37 | DIunion au, bu; | 36 | DIunion au, bu; |
38 | 37 | ||
39 | au.ll = a, bu.ll = b; | 38 | au.ll = a, bu.ll = b; |
40 | 39 | ||
41 | if ((USItype) au.s.high < (USItype) bu.s.high) | 40 | if ((u32) au.s.high < (u32) bu.s.high) |
42 | return 0; | 41 | return 0; |
43 | else if ((USItype) au.s.high > (USItype) bu.s.high) | 42 | else if ((u32) au.s.high > (u32) bu.s.high) |
44 | return 2; | 43 | return 2; |
45 | if ((USItype) au.s.low < (USItype) bu.s.low) | 44 | if ((u32) au.s.low < (u32) bu.s.low) |
46 | return 0; | 45 | return 0; |
47 | else if ((USItype) au.s.low > (USItype) bu.s.low) | 46 | else if ((u32) au.s.low > (u32) bu.s.low) |
48 | return 2; | 47 | return 2; |
49 | return 1; | 48 | return 1; |
50 | } | 49 | } |
51 | |||
diff --git a/arch/arm/lib/udivdi3.c b/arch/arm/lib/udivdi3.c index d25195f673f4..e343be4c6642 100644 --- a/arch/arm/lib/udivdi3.c +++ b/arch/arm/lib/udivdi3.c | |||
@@ -32,211 +32,191 @@ Boston, MA 02111-1307, USA. */ | |||
32 | #include "gcclib.h" | 32 | #include "gcclib.h" |
33 | #include "longlong.h" | 33 | #include "longlong.h" |
34 | 34 | ||
35 | static const UQItype __clz_tab[] = | 35 | static const u8 __clz_tab[] = { |
36 | { | 36 | 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, |
37 | 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, | 37 | 5, 5, 5, 5, 5, 5, 5, 5, |
38 | 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, | 38 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
39 | 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, | 39 | 6, 6, 6, 6, 6, 6, 6, 6, |
40 | 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, | 40 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
41 | 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, | 41 | 7, 7, 7, 7, 7, 7, 7, 7, |
42 | 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, | 42 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
43 | 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, | 43 | 7, 7, 7, 7, 7, 7, 7, 7, |
44 | 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, | 44 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, |
45 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
46 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
47 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
48 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
49 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
50 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
51 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
45 | }; | 52 | }; |
46 | 53 | ||
47 | UDItype | 54 | u64 __udivmoddi4(u64 n, u64 d, u64 * rp) |
48 | __udivmoddi4 (UDItype n, UDItype d, UDItype *rp) | ||
49 | { | 55 | { |
50 | DIunion ww; | 56 | DIunion ww; |
51 | DIunion nn, dd; | 57 | DIunion nn, dd; |
52 | DIunion rr; | 58 | DIunion rr; |
53 | USItype d0, d1, n0, n1, n2; | 59 | u32 d0, d1, n0, n1, n2; |
54 | USItype q0, q1; | 60 | u32 q0, q1; |
55 | USItype b, bm; | 61 | u32 b, bm; |
56 | 62 | ||
57 | nn.ll = n; | 63 | nn.ll = n; |
58 | dd.ll = d; | 64 | dd.ll = d; |
59 | 65 | ||
60 | d0 = dd.s.low; | 66 | d0 = dd.s.low; |
61 | d1 = dd.s.high; | 67 | d1 = dd.s.high; |
62 | n0 = nn.s.low; | 68 | n0 = nn.s.low; |
63 | n1 = nn.s.high; | 69 | n1 = nn.s.high; |
64 | 70 | ||
65 | if (d1 == 0) | 71 | if (d1 == 0) { |
66 | { | 72 | if (d0 > n1) { |
67 | if (d0 > n1) | 73 | /* 0q = nn / 0D */ |
68 | { | 74 | |
69 | /* 0q = nn / 0D */ | 75 | count_leading_zeros(bm, d0); |
70 | 76 | ||
71 | count_leading_zeros (bm, d0); | 77 | if (bm != 0) { |
72 | 78 | /* Normalize, i.e. make the most significant bit of the | |
73 | if (bm != 0) | 79 | denominator set. */ |
74 | { | 80 | |
75 | /* Normalize, i.e. make the most significant bit of the | 81 | d0 = d0 << bm; |
76 | denominator set. */ | 82 | n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm)); |
77 | 83 | n0 = n0 << bm; | |
78 | d0 = d0 << bm; | 84 | } |
79 | n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm)); | 85 | |
80 | n0 = n0 << bm; | 86 | udiv_qrnnd(q0, n0, n1, n0, d0); |
81 | } | 87 | q1 = 0; |
82 | 88 | ||
83 | udiv_qrnnd (q0, n0, n1, n0, d0); | 89 | /* Remainder in n0 >> bm. */ |
84 | q1 = 0; | 90 | } else { |
85 | 91 | /* qq = NN / 0d */ | |
86 | /* Remainder in n0 >> bm. */ | 92 | |
87 | } | 93 | if (d0 == 0) |
88 | else | 94 | d0 = 1 / d0; /* Divide intentionally by zero. */ |
89 | { | 95 | |
90 | /* qq = NN / 0d */ | 96 | count_leading_zeros(bm, d0); |
91 | 97 | ||
92 | if (d0 == 0) | 98 | if (bm == 0) { |
93 | d0 = 1 / d0; /* Divide intentionally by zero. */ | 99 | /* From (n1 >= d0) /\ (the most significant bit of d0 is set), |
94 | 100 | conclude (the most significant bit of n1 is set) /\ (the | |
95 | count_leading_zeros (bm, d0); | 101 | leading quotient digit q1 = 1). |
96 | 102 | ||
97 | if (bm == 0) | 103 | This special case is necessary, not an optimization. |
98 | { | 104 | (Shifts counts of SI_TYPE_SIZE are undefined.) */ |
99 | /* From (n1 >= d0) /\ (the most significant bit of d0 is set), | 105 | |
100 | conclude (the most significant bit of n1 is set) /\ (the | 106 | n1 -= d0; |
101 | leading quotient digit q1 = 1). | 107 | q1 = 1; |
102 | 108 | } else { | |
103 | This special case is necessary, not an optimization. | 109 | /* Normalize. */ |
104 | (Shifts counts of SI_TYPE_SIZE are undefined.) */ | 110 | |
105 | 111 | b = SI_TYPE_SIZE - bm; | |
106 | n1 -= d0; | 112 | |
107 | q1 = 1; | 113 | d0 = d0 << bm; |
108 | } | 114 | n2 = n1 >> b; |
109 | else | 115 | n1 = (n1 << bm) | (n0 >> b); |
110 | { | 116 | n0 = n0 << bm; |
111 | /* Normalize. */ | 117 | |
112 | 118 | udiv_qrnnd(q1, n1, n2, n1, d0); | |
113 | b = SI_TYPE_SIZE - bm; | 119 | } |
114 | 120 | ||
115 | d0 = d0 << bm; | 121 | /* n1 != d0... */ |
116 | n2 = n1 >> b; | 122 | |
117 | n1 = (n1 << bm) | (n0 >> b); | 123 | udiv_qrnnd(q0, n0, n1, n0, d0); |
118 | n0 = n0 << bm; | 124 | |
119 | 125 | /* Remainder in n0 >> bm. */ | |
120 | udiv_qrnnd (q1, n1, n2, n1, d0); | 126 | } |
121 | } | 127 | |
122 | 128 | if (rp != 0) { | |
123 | /* n1 != d0... */ | 129 | rr.s.low = n0 >> bm; |
124 | 130 | rr.s.high = 0; | |
125 | udiv_qrnnd (q0, n0, n1, n0, d0); | 131 | *rp = rr.ll; |
126 | 132 | } | |
127 | /* Remainder in n0 >> bm. */ | 133 | } else { |
128 | } | 134 | if (d1 > n1) { |
129 | 135 | /* 00 = nn / DD */ | |
130 | if (rp != 0) | 136 | |
131 | { | 137 | q0 = 0; |
132 | rr.s.low = n0 >> bm; | 138 | q1 = 0; |
133 | rr.s.high = 0; | 139 | |
134 | *rp = rr.ll; | 140 | /* Remainder in n1n0. */ |
135 | } | 141 | if (rp != 0) { |
136 | } | 142 | rr.s.low = n0; |
137 | else | 143 | rr.s.high = n1; |
138 | { | 144 | *rp = rr.ll; |
139 | if (d1 > n1) | 145 | } |
140 | { | 146 | } else { |
141 | /* 00 = nn / DD */ | 147 | /* 0q = NN / dd */ |
142 | 148 | ||
143 | q0 = 0; | 149 | count_leading_zeros(bm, d1); |
144 | q1 = 0; | 150 | if (bm == 0) { |
145 | 151 | /* From (n1 >= d1) /\ (the most significant bit of d1 is set), | |
146 | /* Remainder in n1n0. */ | 152 | conclude (the most significant bit of n1 is set) /\ (the |
147 | if (rp != 0) | 153 | quotient digit q0 = 0 or 1). |
148 | { | 154 | |
149 | rr.s.low = n0; | 155 | This special case is necessary, not an optimization. */ |
150 | rr.s.high = n1; | 156 | |
151 | *rp = rr.ll; | 157 | /* The condition on the next line takes advantage of that |
152 | } | 158 | n1 >= d1 (true due to program flow). */ |
153 | } | 159 | if (n1 > d1 || n0 >= d0) { |
154 | else | 160 | q0 = 1; |
155 | { | 161 | sub_ddmmss(n1, n0, n1, n0, d1, d0); |
156 | /* 0q = NN / dd */ | 162 | } else |
157 | 163 | q0 = 0; | |
158 | count_leading_zeros (bm, d1); | 164 | |
159 | if (bm == 0) | 165 | q1 = 0; |
160 | { | 166 | |
161 | /* From (n1 >= d1) /\ (the most significant bit of d1 is set), | 167 | if (rp != 0) { |
162 | conclude (the most significant bit of n1 is set) /\ (the | 168 | rr.s.low = n0; |
163 | quotient digit q0 = 0 or 1). | 169 | rr.s.high = n1; |
164 | 170 | *rp = rr.ll; | |
165 | This special case is necessary, not an optimization. */ | 171 | } |
166 | 172 | } else { | |
167 | /* The condition on the next line takes advantage of that | 173 | u32 m1, m0; |
168 | n1 >= d1 (true due to program flow). */ | 174 | /* Normalize. */ |
169 | if (n1 > d1 || n0 >= d0) | 175 | |
170 | { | 176 | b = SI_TYPE_SIZE - bm; |
171 | q0 = 1; | 177 | |
172 | sub_ddmmss (n1, n0, n1, n0, d1, d0); | 178 | d1 = (d1 << bm) | (d0 >> b); |
173 | } | 179 | d0 = d0 << bm; |
174 | else | 180 | n2 = n1 >> b; |
175 | q0 = 0; | 181 | n1 = (n1 << bm) | (n0 >> b); |
176 | 182 | n0 = n0 << bm; | |
177 | q1 = 0; | 183 | |
178 | 184 | udiv_qrnnd(q0, n1, n2, n1, d1); | |
179 | if (rp != 0) | 185 | umul_ppmm(m1, m0, q0, d0); |
180 | { | 186 | |
181 | rr.s.low = n0; | 187 | if (m1 > n1 || (m1 == n1 && m0 > n0)) { |
182 | rr.s.high = n1; | 188 | q0--; |
183 | *rp = rr.ll; | 189 | sub_ddmmss(m1, m0, m1, m0, d1, d0); |
184 | } | 190 | } |
185 | } | 191 | |
186 | else | 192 | q1 = 0; |
187 | { | 193 | |
188 | USItype m1, m0; | 194 | /* Remainder in (n1n0 - m1m0) >> bm. */ |
189 | /* Normalize. */ | 195 | if (rp != 0) { |
190 | 196 | sub_ddmmss(n1, n0, n1, n0, m1, m0); | |
191 | b = SI_TYPE_SIZE - bm; | 197 | rr.s.low = (n1 << b) | (n0 >> bm); |
192 | 198 | rr.s.high = n1 >> bm; | |
193 | d1 = (d1 << bm) | (d0 >> b); | 199 | *rp = rr.ll; |
194 | d0 = d0 << bm; | 200 | } |
195 | n2 = n1 >> b; | 201 | } |
196 | n1 = (n1 << bm) | (n0 >> b); | 202 | } |
197 | n0 = n0 << bm; | 203 | } |
198 | 204 | ||
199 | udiv_qrnnd (q0, n1, n2, n1, d1); | 205 | ww.s.low = q0; |
200 | umul_ppmm (m1, m0, q0, d0); | 206 | ww.s.high = q1; |
201 | 207 | return ww.ll; | |
202 | if (m1 > n1 || (m1 == n1 && m0 > n0)) | ||
203 | { | ||
204 | q0--; | ||
205 | sub_ddmmss (m1, m0, m1, m0, d1, d0); | ||
206 | } | ||
207 | |||
208 | q1 = 0; | ||
209 | |||
210 | /* Remainder in (n1n0 - m1m0) >> bm. */ | ||
211 | if (rp != 0) | ||
212 | { | ||
213 | sub_ddmmss (n1, n0, n1, n0, m1, m0); | ||
214 | rr.s.low = (n1 << b) | (n0 >> bm); | ||
215 | rr.s.high = n1 >> bm; | ||
216 | *rp = rr.ll; | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | ww.s.low = q0; | ||
223 | ww.s.high = q1; | ||
224 | return ww.ll; | ||
225 | } | 208 | } |
226 | 209 | ||
227 | UDItype | 210 | u64 __udivdi3(u64 n, u64 d) |
228 | __udivdi3 (UDItype n, UDItype d) | ||
229 | { | 211 | { |
230 | return __udivmoddi4 (n, d, (UDItype *) 0); | 212 | return __udivmoddi4(n, d, (u64 *) 0); |
231 | } | 213 | } |
232 | 214 | ||
233 | UDItype | 215 | u64 __umoddi3(u64 u, u64 v) |
234 | __umoddi3 (UDItype u, UDItype v) | ||
235 | { | 216 | { |
236 | UDItype w; | 217 | u64 w; |
237 | 218 | ||
238 | (void) __udivmoddi4 (u ,v, &w); | 219 | (void)__udivmoddi4(u, v, &w); |
239 | 220 | ||
240 | return w; | 221 | return w; |
241 | } | 222 | } |
242 | |||
diff --git a/arch/arm/mach-aaec2000/Kconfig b/arch/arm/mach-aaec2000/Kconfig new file mode 100644 index 000000000000..5e4bef93754c --- /dev/null +++ b/arch/arm/mach-aaec2000/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | if ARCH_AAEC2000 | ||
2 | |||
3 | menu "Agilent AAEC-2000 Implementations" | ||
4 | |||
5 | config MACH_AAED2000 | ||
6 | bool "Agilent AAED-2000 Development Platform" | ||
7 | select CPU_ARM920T | ||
8 | |||
9 | endmenu | ||
10 | |||
11 | endif | ||
diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile new file mode 100644 index 000000000000..20ec83896c37 --- /dev/null +++ b/arch/arm/mach-aaec2000/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | # Common support (must be linked before board specific support) | ||
6 | obj-y += core.o | ||
7 | |||
8 | # Specific board support | ||
9 | 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 index 000000000000..5417ca3f4621 --- /dev/null +++ b/arch/arm/mach-aaec2000/aaed2000.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-aaec2000/aaed2000.c | ||
3 | * | ||
4 | * Support for the Agilent AAED-2000 Development Platform. | ||
5 | * | ||
6 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/major.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | |||
20 | #include <asm/setup.h> | ||
21 | #include <asm/memory.h> | ||
22 | #include <asm/mach-types.h> | ||
23 | #include <asm/hardware.h> | ||
24 | #include <asm/irq.h> | ||
25 | |||
26 | #include <asm/mach/arch.h> | ||
27 | #include <asm/mach/map.h> | ||
28 | #include <asm/mach/irq.h> | ||
29 | |||
30 | #include "core.h" | ||
31 | |||
32 | static void __init aaed2000_init_irq(void) | ||
33 | { | ||
34 | aaec2000_init_irq(); | ||
35 | } | ||
36 | |||
37 | static void __init aaed2000_map_io(void) | ||
38 | { | ||
39 | aaec2000_map_io(); | ||
40 | } | ||
41 | |||
42 | MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform") | ||
43 | MAINTAINER("Nicolas Bellido Y Ortega") | ||
44 | BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE) | ||
45 | MAPIO(aaed2000_map_io) | ||
46 | INITIRQ(aaed2000_init_irq) | ||
47 | .timer = &aaec2000_timer, | ||
48 | MACHINE_END | ||
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c new file mode 100644 index 000000000000..fc145b3768fa --- /dev/null +++ b/arch/arm/mach-aaec2000/core.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-aaec2000/core.c | ||
3 | * | ||
4 | * Code common to all AAEC-2000 machines | ||
5 | * | ||
6 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/config.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/timex.h> | ||
20 | #include <linux/signal.h> | ||
21 | |||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/irq.h> | ||
24 | |||
25 | #include <asm/mach/irq.h> | ||
26 | #include <asm/mach/time.h> | ||
27 | #include <asm/mach/map.h> | ||
28 | |||
29 | /* | ||
30 | * Common I/O mapping: | ||
31 | * | ||
32 | * Static virtual address mappings are as follow: | ||
33 | * | ||
34 | * 0xf8000000-0xf8001ffff: Devices connected to APB bus | ||
35 | * 0xf8002000-0xf8003ffff: Devices connected to AHB bus | ||
36 | * | ||
37 | * Below 0xe8000000 is reserved for vm allocation. | ||
38 | * | ||
39 | * The machine specific code must provide the extra mapping beside the | ||
40 | * default mapping provided here. | ||
41 | */ | ||
42 | static struct map_desc standard_io_desc[] __initdata = { | ||
43 | /* virtual physical length type */ | ||
44 | { VIO_APB_BASE, PIO_APB_BASE, IO_APB_LENGTH, MT_DEVICE }, | ||
45 | { VIO_AHB_BASE, PIO_AHB_BASE, IO_AHB_LENGTH, MT_DEVICE } | ||
46 | }; | ||
47 | |||
48 | void __init aaec2000_map_io(void) | ||
49 | { | ||
50 | iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Interrupt handling routines | ||
55 | */ | ||
56 | static void aaec2000_int_ack(unsigned int irq) | ||
57 | { | ||
58 | IRQ_INTSR = 1 << irq; | ||
59 | } | ||
60 | |||
61 | static void aaec2000_int_mask(unsigned int irq) | ||
62 | { | ||
63 | IRQ_INTENC |= (1 << irq); | ||
64 | } | ||
65 | |||
66 | static void aaec2000_int_unmask(unsigned int irq) | ||
67 | { | ||
68 | IRQ_INTENS |= (1 << irq); | ||
69 | } | ||
70 | |||
71 | static struct irqchip aaec2000_irq_chip = { | ||
72 | .ack = aaec2000_int_ack, | ||
73 | .mask = aaec2000_int_mask, | ||
74 | .unmask = aaec2000_int_unmask, | ||
75 | }; | ||
76 | |||
77 | void __init aaec2000_init_irq(void) | ||
78 | { | ||
79 | unsigned int i; | ||
80 | |||
81 | for (i = 0; i < NR_IRQS; i++) { | ||
82 | set_irq_handler(i, do_level_IRQ); | ||
83 | set_irq_chip(i, &aaec2000_irq_chip); | ||
84 | set_irq_flags(i, IRQF_VALID); | ||
85 | } | ||
86 | |||
87 | /* Disable all interrupts */ | ||
88 | IRQ_INTENC = 0xffffffff; | ||
89 | |||
90 | /* Clear any pending interrupts */ | ||
91 | IRQ_INTSR = IRQ_INTSR; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Time keeping | ||
96 | */ | ||
97 | /* IRQs are disabled before entering here from do_gettimeofday() */ | ||
98 | static unsigned long aaec2000_gettimeoffset(void) | ||
99 | { | ||
100 | unsigned long ticks_to_match, elapsed, usec; | ||
101 | |||
102 | /* Get ticks before next timer match */ | ||
103 | ticks_to_match = TIMER1_LOAD - TIMER1_VAL; | ||
104 | |||
105 | /* We need elapsed ticks since last match */ | ||
106 | elapsed = LATCH - ticks_to_match; | ||
107 | |||
108 | /* Now, convert them to usec */ | ||
109 | usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH; | ||
110 | |||
111 | return usec; | ||
112 | } | ||
113 | |||
114 | /* We enter here with IRQs enabled */ | ||
115 | static irqreturn_t | ||
116 | aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
117 | { | ||
118 | /* TODO: Check timer accuracy */ | ||
119 | write_seqlock(&xtime_lock); | ||
120 | |||
121 | timer_tick(regs); | ||
122 | TIMER1_CLEAR = 1; | ||
123 | |||
124 | write_sequnlock(&xtime_lock); | ||
125 | |||
126 | return IRQ_HANDLED; | ||
127 | } | ||
128 | |||
129 | static struct irqaction aaec2000_timer_irq = { | ||
130 | .name = "AAEC-2000 Timer Tick", | ||
131 | .flags = SA_INTERRUPT, | ||
132 | .handler = aaec2000_timer_interrupt | ||
133 | }; | ||
134 | |||
135 | static void __init aaec2000_timer_init(void) | ||
136 | { | ||
137 | /* Disable timer 1 */ | ||
138 | TIMER1_CTRL = 0; | ||
139 | |||
140 | /* We have somehow to generate a 100Hz clock. | ||
141 | * We then use the 508KHz timer in periodic mode. | ||
142 | */ | ||
143 | TIMER1_LOAD = LATCH; | ||
144 | TIMER1_CLEAR = 1; /* Clear interrupt */ | ||
145 | |||
146 | setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq); | ||
147 | |||
148 | TIMER1_CTRL = TIMER_CTRL_ENABLE | | ||
149 | TIMER_CTRL_PERIODIC | | ||
150 | TIMER_CTRL_CLKSEL_508K; | ||
151 | } | ||
152 | |||
153 | struct sys_timer aaec2000_timer = { | ||
154 | .init = aaec2000_timer_init, | ||
155 | .offset = aaec2000_gettimeoffset, | ||
156 | }; | ||
157 | |||
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h new file mode 100644 index 000000000000..91893d848c16 --- /dev/null +++ b/arch/arm/mach-aaec2000/core.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-aaec2000/core.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | struct sys_timer; | ||
13 | |||
14 | extern struct sys_timer aaec2000_timer; | ||
15 | extern void __init aaec2000_map_io(void); | ||
16 | extern void __init aaec2000_init_irq(void); | ||
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index d302f0405fd2..bd1e5e3c9d34 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c | |||
@@ -227,7 +227,6 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
227 | * primary CPU | 227 | * primary CPU |
228 | */ | 228 | */ |
229 | if (hard_smp_processor_id() == 0) { | 229 | if (hard_smp_processor_id() == 0) { |
230 | nmi_tick(); | ||
231 | timer_tick(regs); | 230 | timer_tick(regs); |
232 | #ifdef CONFIG_SMP | 231 | #ifdef CONFIG_SMP |
233 | smp_send_timer(); | 232 | smp_send_timer(); |
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 4f3c3d5c781c..fc0555596d6d 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c | |||
@@ -162,12 +162,13 @@ void __init ixp2000_map_io(void) | |||
162 | static unsigned ticks_per_jiffy; | 162 | static unsigned ticks_per_jiffy; |
163 | static unsigned ticks_per_usec; | 163 | static unsigned ticks_per_usec; |
164 | static unsigned next_jiffy_time; | 164 | static unsigned next_jiffy_time; |
165 | static volatile unsigned long *missing_jiffy_timer_csr; | ||
165 | 166 | ||
166 | unsigned long ixp2000_gettimeoffset (void) | 167 | unsigned long ixp2000_gettimeoffset (void) |
167 | { | 168 | { |
168 | unsigned long offset; | 169 | unsigned long offset; |
169 | 170 | ||
170 | offset = next_jiffy_time - *IXP2000_T4_CSR; | 171 | offset = next_jiffy_time - *missing_jiffy_timer_csr; |
171 | 172 | ||
172 | return offset / ticks_per_usec; | 173 | return offset / ticks_per_usec; |
173 | } | 174 | } |
@@ -179,7 +180,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
179 | /* clear timer 1 */ | 180 | /* clear timer 1 */ |
180 | ixp2000_reg_write(IXP2000_T1_CLR, 1); | 181 | ixp2000_reg_write(IXP2000_T1_CLR, 1); |
181 | 182 | ||
182 | while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) { | 183 | while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) { |
183 | timer_tick(regs); | 184 | timer_tick(regs); |
184 | next_jiffy_time -= ticks_per_jiffy; | 185 | next_jiffy_time -= ticks_per_jiffy; |
185 | } | 186 | } |
@@ -197,20 +198,37 @@ static struct irqaction ixp2000_timer_irq = { | |||
197 | 198 | ||
198 | void __init ixp2000_init_time(unsigned long tick_rate) | 199 | void __init ixp2000_init_time(unsigned long tick_rate) |
199 | { | 200 | { |
200 | ixp2000_reg_write(IXP2000_T1_CLR, 0); | ||
201 | ixp2000_reg_write(IXP2000_T4_CLR, 0); | ||
202 | |||
203 | ticks_per_jiffy = (tick_rate + HZ/2) / HZ; | 201 | ticks_per_jiffy = (tick_rate + HZ/2) / HZ; |
204 | ticks_per_usec = tick_rate / 1000000; | 202 | ticks_per_usec = tick_rate / 1000000; |
205 | 203 | ||
204 | /* | ||
205 | * We use timer 1 as our timer interrupt. | ||
206 | */ | ||
207 | ixp2000_reg_write(IXP2000_T1_CLR, 0); | ||
206 | ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1); | 208 | ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1); |
207 | ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7)); | 209 | ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7)); |
208 | 210 | ||
209 | /* | 211 | /* |
210 | * We use T4 as a monotonic counter to track missed jiffies | 212 | * We use a second timer as a monotonic counter for tracking |
213 | * missed jiffies. The IXP2000 has four timers, but if we're | ||
214 | * on an A-step IXP2800, timer 2 and 3 don't work, so on those | ||
215 | * chips we use timer 4. Timer 4 is the only timer that can | ||
216 | * be used for the watchdog, so we use timer 2 if we're on a | ||
217 | * non-buggy chip. | ||
211 | */ | 218 | */ |
212 | ixp2000_reg_write(IXP2000_T4_CLD, -1); | 219 | if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) { |
213 | ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7)); | 220 | printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n"); |
221 | |||
222 | ixp2000_reg_write(IXP2000_T4_CLR, 0); | ||
223 | ixp2000_reg_write(IXP2000_T4_CLD, -1); | ||
224 | ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7)); | ||
225 | missing_jiffy_timer_csr = IXP2000_T4_CSR; | ||
226 | } else { | ||
227 | ixp2000_reg_write(IXP2000_T2_CLR, 0); | ||
228 | ixp2000_reg_write(IXP2000_T2_CLD, -1); | ||
229 | ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7)); | ||
230 | missing_jiffy_timer_csr = IXP2000_T2_CSR; | ||
231 | } | ||
214 | next_jiffy_time = 0xffffffff; | 232 | next_jiffy_time = 0xffffffff; |
215 | 233 | ||
216 | /* register for interrupt */ | 234 | /* register for interrupt */ |
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile index 5d608837757a..ba81e70ed813 100644 --- a/arch/arm/mach-versatile/Makefile +++ b/arch/arm/mach-versatile/Makefile | |||
@@ -5,3 +5,4 @@ | |||
5 | obj-y := core.o clock.o | 5 | obj-y := core.o clock.o |
6 | obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o | 6 | obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o |
7 | obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o | 7 | obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o |
8 | obj-$(CONFIG_PCI) += pci.o | ||
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 302c2a7b9b63..6a7cbea5e098 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c | |||
@@ -196,11 +196,15 @@ static struct map_desc versatile_io_desc[] __initdata = { | |||
196 | #ifdef CONFIG_DEBUG_LL | 196 | #ifdef CONFIG_DEBUG_LL |
197 | { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE }, | 197 | { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE }, |
198 | #endif | 198 | #endif |
199 | #ifdef FIXME | 199 | #ifdef CONFIG_PCI |
200 | { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE }, | 200 | { IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE }, |
201 | { PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE }, | 201 | { VERSATILE_PCI_VIRT_BASE, VERSATILE_PCI_BASE, VERSATILE_PCI_BASE_SIZE, MT_DEVICE }, |
202 | { PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE }, | 202 | { VERSATILE_PCI_CFG_VIRT_BASE, VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE }, |
203 | { PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE }, | 203 | #if 0 |
204 | { VERSATILE_PCI_VIRT_MEM_BASE0, VERSATILE_PCI_MEM_BASE0, SZ_16M, MT_DEVICE }, | ||
205 | { VERSATILE_PCI_VIRT_MEM_BASE1, VERSATILE_PCI_MEM_BASE1, SZ_16M, MT_DEVICE }, | ||
206 | { VERSATILE_PCI_VIRT_MEM_BASE2, VERSATILE_PCI_MEM_BASE2, SZ_16M, MT_DEVICE }, | ||
207 | #endif | ||
204 | #endif | 208 | #endif |
205 | }; | 209 | }; |
206 | 210 | ||
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c new file mode 100644 index 000000000000..d1565e851f0e --- /dev/null +++ b/arch/arm/mach-versatile/pci.c | |||
@@ -0,0 +1,360 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-versatile/pci.c | ||
3 | * | ||
4 | * (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved. | ||
5 | * You can redistribute and/or modify this software under the terms of version 2 | ||
6 | * of the GNU General Public License as published by the Free Software Foundation. | ||
7 | * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED | ||
8 | * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
9 | * General Public License for more details. | ||
10 | * Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software. | ||
11 | * | ||
12 | * ARM Versatile PCI driver. | ||
13 | * | ||
14 | * 14/04/2005 Initial version, colin.king@philips.com | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/config.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/ptrace.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/init.h> | ||
26 | |||
27 | #include <asm/hardware.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/irq.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/mach/pci.h> | ||
32 | #include <asm/mach-types.h> | ||
33 | |||
34 | /* | ||
35 | * these spaces are mapped using the following base registers: | ||
36 | * | ||
37 | * Usage Local Bus Memory Base/Map registers used | ||
38 | * | ||
39 | * Mem 50000000 - 5FFFFFFF LB_BASE0/LB_MAP0, non prefetch | ||
40 | * Mem 60000000 - 6FFFFFFF LB_BASE1/LB_MAP1, prefetch | ||
41 | * IO 44000000 - 4FFFFFFF LB_BASE2/LB_MAP2, IO | ||
42 | * Cfg 42000000 - 42FFFFFF PCI config | ||
43 | * | ||
44 | */ | ||
45 | #define SYS_PCICTL IO_ADDRESS(VERSATILE_SYS_PCICTL) | ||
46 | #define PCI_IMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0) | ||
47 | #define PCI_IMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4) | ||
48 | #define PCI_IMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8) | ||
49 | #define PCI_SMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10) | ||
50 | #define PCI_SMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14) | ||
51 | #define PCI_SMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18) | ||
52 | #define PCI_SELFID IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc) | ||
53 | |||
54 | #define DEVICE_ID_OFFSET 0x00 | ||
55 | #define CSR_OFFSET 0x04 | ||
56 | #define CLASS_ID_OFFSET 0x08 | ||
57 | |||
58 | #define VP_PCI_DEVICE_ID 0x030010ee | ||
59 | #define VP_PCI_CLASS_ID 0x0b400000 | ||
60 | |||
61 | static unsigned long pci_slot_ignore = 0; | ||
62 | |||
63 | static int __init versatile_pci_slot_ignore(char *str) | ||
64 | { | ||
65 | int retval; | ||
66 | int slot; | ||
67 | |||
68 | while ((retval = get_option(&str,&slot))) { | ||
69 | if ((slot < 0) || (slot > 31)) { | ||
70 | printk("Illegal slot value: %d\n",slot); | ||
71 | } else { | ||
72 | pci_slot_ignore |= (1 << slot); | ||
73 | } | ||
74 | } | ||
75 | return 1; | ||
76 | } | ||
77 | |||
78 | __setup("pci_slot_ignore=", versatile_pci_slot_ignore); | ||
79 | |||
80 | |||
81 | static unsigned long __pci_addr(struct pci_bus *bus, | ||
82 | unsigned int devfn, int offset) | ||
83 | { | ||
84 | unsigned int busnr = bus->number; | ||
85 | |||
86 | /* | ||
87 | * Trap out illegal values | ||
88 | */ | ||
89 | if (offset > 255) | ||
90 | BUG(); | ||
91 | if (busnr > 255) | ||
92 | BUG(); | ||
93 | if (devfn > 255) | ||
94 | BUG(); | ||
95 | |||
96 | return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) | | ||
97 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset); | ||
98 | } | ||
99 | |||
100 | static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
101 | int size, u32 *val) | ||
102 | { | ||
103 | unsigned long addr = __pci_addr(bus, devfn, where); | ||
104 | u32 v; | ||
105 | int slot = PCI_SLOT(devfn); | ||
106 | |||
107 | if (pci_slot_ignore & (1 << slot)) { | ||
108 | /* Ignore this slot */ | ||
109 | switch (size) { | ||
110 | case 1: | ||
111 | v = 0xff; | ||
112 | break; | ||
113 | case 2: | ||
114 | v = 0xffff; | ||
115 | break; | ||
116 | default: | ||
117 | v = 0xffffffff; | ||
118 | } | ||
119 | } else { | ||
120 | switch (size) { | ||
121 | case 1: | ||
122 | addr &= ~3; | ||
123 | v = __raw_readb(addr); | ||
124 | break; | ||
125 | |||
126 | case 2: | ||
127 | v = __raw_readl(addr & ~3); | ||
128 | if (addr & 2) v >>= 16; | ||
129 | v &= 0xffff; | ||
130 | break; | ||
131 | |||
132 | default: | ||
133 | addr &= ~3; | ||
134 | v = __raw_readl(addr); | ||
135 | break; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | *val = v; | ||
140 | return PCIBIOS_SUCCESSFUL; | ||
141 | } | ||
142 | |||
143 | static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
144 | int size, u32 val) | ||
145 | { | ||
146 | unsigned long addr = __pci_addr(bus, devfn, where); | ||
147 | int slot = PCI_SLOT(devfn); | ||
148 | |||
149 | if (pci_slot_ignore & (1 << slot)) { | ||
150 | return PCIBIOS_SUCCESSFUL; | ||
151 | } | ||
152 | |||
153 | switch (size) { | ||
154 | case 1: | ||
155 | __raw_writeb((u8)val, addr); | ||
156 | break; | ||
157 | |||
158 | case 2: | ||
159 | __raw_writew((u16)val, addr); | ||
160 | break; | ||
161 | |||
162 | case 4: | ||
163 | __raw_writel(val, addr); | ||
164 | break; | ||
165 | } | ||
166 | |||
167 | return PCIBIOS_SUCCESSFUL; | ||
168 | } | ||
169 | |||
170 | static struct pci_ops pci_versatile_ops = { | ||
171 | .read = versatile_read_config, | ||
172 | .write = versatile_write_config, | ||
173 | }; | ||
174 | |||
175 | static struct resource io_mem = { | ||
176 | .name = "PCI I/O space", | ||
177 | .start = VERSATILE_PCI_MEM_BASE0, | ||
178 | .end = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1, | ||
179 | .flags = IORESOURCE_IO, | ||
180 | }; | ||
181 | |||
182 | static struct resource non_mem = { | ||
183 | .name = "PCI non-prefetchable", | ||
184 | .start = VERSATILE_PCI_MEM_BASE1, | ||
185 | .end = VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1, | ||
186 | .flags = IORESOURCE_MEM, | ||
187 | }; | ||
188 | |||
189 | static struct resource pre_mem = { | ||
190 | .name = "PCI prefetchable", | ||
191 | .start = VERSATILE_PCI_MEM_BASE2, | ||
192 | .end = VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1, | ||
193 | .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, | ||
194 | }; | ||
195 | |||
196 | static int __init pci_versatile_setup_resources(struct resource **resource) | ||
197 | { | ||
198 | int ret = 0; | ||
199 | |||
200 | ret = request_resource(&iomem_resource, &io_mem); | ||
201 | if (ret) { | ||
202 | printk(KERN_ERR "PCI: unable to allocate I/O " | ||
203 | "memory region (%d)\n", ret); | ||
204 | goto out; | ||
205 | } | ||
206 | ret = request_resource(&iomem_resource, &non_mem); | ||
207 | if (ret) { | ||
208 | printk(KERN_ERR "PCI: unable to allocate non-prefetchable " | ||
209 | "memory region (%d)\n", ret); | ||
210 | goto release_io_mem; | ||
211 | } | ||
212 | ret = request_resource(&iomem_resource, &pre_mem); | ||
213 | if (ret) { | ||
214 | printk(KERN_ERR "PCI: unable to allocate prefetchable " | ||
215 | "memory region (%d)\n", ret); | ||
216 | goto release_non_mem; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * bus->resource[0] is the IO resource for this bus | ||
221 | * bus->resource[1] is the mem resource for this bus | ||
222 | * bus->resource[2] is the prefetch mem resource for this bus | ||
223 | */ | ||
224 | resource[0] = &io_mem; | ||
225 | resource[1] = &non_mem; | ||
226 | resource[2] = &pre_mem; | ||
227 | |||
228 | goto out; | ||
229 | |||
230 | release_non_mem: | ||
231 | release_resource(&non_mem); | ||
232 | release_io_mem: | ||
233 | release_resource(&io_mem); | ||
234 | out: | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | int __init pci_versatile_setup(int nr, struct pci_sys_data *sys) | ||
239 | { | ||
240 | int ret = 0; | ||
241 | int i; | ||
242 | int myslot = -1; | ||
243 | unsigned long val; | ||
244 | |||
245 | if (nr == 0) { | ||
246 | sys->mem_offset = 0; | ||
247 | ret = pci_versatile_setup_resources(sys->resource); | ||
248 | if (ret < 0) { | ||
249 | printk("pci_versatile_setup: resources... oops?\n"); | ||
250 | goto out; | ||
251 | } | ||
252 | } else { | ||
253 | printk("pci_versatile_setup: resources... nr == 0??\n"); | ||
254 | goto out; | ||
255 | } | ||
256 | |||
257 | __raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0); | ||
258 | __raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1); | ||
259 | __raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2); | ||
260 | |||
261 | __raw_writel(1, SYS_PCICTL); | ||
262 | |||
263 | val = __raw_readl(SYS_PCICTL); | ||
264 | if (!(val & 1)) { | ||
265 | printk("Not plugged into PCI backplane!\n"); | ||
266 | ret = -EIO; | ||
267 | goto out; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * We need to discover the PCI core first to configure itself | ||
272 | * before the main PCI probing is performed | ||
273 | */ | ||
274 | for (i=0; i<32; i++) { | ||
275 | if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) && | ||
276 | (__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) { | ||
277 | myslot = i; | ||
278 | |||
279 | __raw_writel(myslot, PCI_SELFID); | ||
280 | val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET); | ||
281 | val |= (1<<2); | ||
282 | __raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET); | ||
283 | break; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | if (myslot == -1) { | ||
288 | printk("Cannot find PCI core!\n"); | ||
289 | ret = -EIO; | ||
290 | } else { | ||
291 | printk("PCI core found (slot %d)\n",myslot); | ||
292 | /* Do not to map Versatile FPGA PCI device | ||
293 | into memory space as we are short of | ||
294 | mappable memory */ | ||
295 | pci_slot_ignore |= (1 << myslot); | ||
296 | ret = 1; | ||
297 | } | ||
298 | |||
299 | out: | ||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | |||
304 | struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys) | ||
305 | { | ||
306 | return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys); | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * V3_LB_BASE? - local bus address | ||
311 | * V3_LB_MAP? - pci bus address | ||
312 | */ | ||
313 | void __init pci_versatile_preinit(void) | ||
314 | { | ||
315 | } | ||
316 | |||
317 | void __init pci_versatile_postinit(void) | ||
318 | { | ||
319 | } | ||
320 | |||
321 | |||
322 | /* | ||
323 | * map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this. | ||
324 | */ | ||
325 | static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
326 | { | ||
327 | int irq; | ||
328 | int devslot = PCI_SLOT(dev->devfn); | ||
329 | |||
330 | /* slot, pin, irq | ||
331 | 24 1 27 | ||
332 | 25 1 28 untested | ||
333 | 26 1 29 | ||
334 | 27 1 30 untested | ||
335 | */ | ||
336 | |||
337 | irq = 27 + ((slot + pin + 2) % 3); /* Fudged */ | ||
338 | |||
339 | printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq); | ||
340 | |||
341 | return irq; | ||
342 | } | ||
343 | |||
344 | static struct hw_pci versatile_pci __initdata = { | ||
345 | .swizzle = NULL, | ||
346 | .map_irq = versatile_map_irq, | ||
347 | .nr_controllers = 1, | ||
348 | .setup = pci_versatile_setup, | ||
349 | .scan = pci_versatile_scan_bus, | ||
350 | .preinit = pci_versatile_preinit, | ||
351 | .postinit = pci_versatile_postinit, | ||
352 | }; | ||
353 | |||
354 | static int __init versatile_pci_init(void) | ||
355 | { | ||
356 | pci_common_init(&versatile_pci); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | subsys_initcall(versatile_pci_init); | ||
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 3fefb43c67f7..95606b4a3ba6 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -62,7 +62,7 @@ config CPU_ARM720T | |||
62 | # ARM920T | 62 | # ARM920T |
63 | config CPU_ARM920T | 63 | config CPU_ARM920T |
64 | bool "Support ARM920T processor" if !ARCH_S3C2410 | 64 | bool "Support ARM920T processor" if !ARCH_S3C2410 |
65 | depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX | 65 | depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 |
66 | default y if ARCH_S3C2410 | 66 | default y if ARCH_S3C2410 |
67 | select CPU_32v4 | 67 | select CPU_32v4 |
68 | select CPU_ABRT_EV4T | 68 | select CPU_ABRT_EV4T |
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index a8c00236bd3d..27d041574ea7 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c | |||
@@ -30,8 +30,6 @@ | |||
30 | 30 | ||
31 | static DEFINE_SPINLOCK(v6_lock); | 31 | static DEFINE_SPINLOCK(v6_lock); |
32 | 32 | ||
33 | #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) | ||
34 | |||
35 | /* | 33 | /* |
36 | * Copy the user page. No aliasing to deal with so we can just | 34 | * Copy the user page. No aliasing to deal with so we can just |
37 | * attack the kernel's existing mapping of these pages. | 35 | * attack the kernel's existing mapping of these pages. |
@@ -55,7 +53,7 @@ void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr) | |||
55 | */ | 53 | */ |
56 | void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr) | 54 | void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr) |
57 | { | 55 | { |
58 | unsigned int offset = DCACHE_COLOUR(vaddr); | 56 | unsigned int offset = CACHE_COLOUR(vaddr); |
59 | unsigned long from, to; | 57 | unsigned long from, to; |
60 | 58 | ||
61 | /* | 59 | /* |
@@ -95,7 +93,7 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd | |||
95 | */ | 93 | */ |
96 | void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) | 94 | void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) |
97 | { | 95 | { |
98 | unsigned int offset = DCACHE_COLOUR(vaddr); | 96 | unsigned int offset = CACHE_COLOUR(vaddr); |
99 | unsigned long to = to_address + (offset << PAGE_SHIFT); | 97 | unsigned long to = to_address + (offset << PAGE_SHIFT); |
100 | 98 | ||
101 | /* | 99 | /* |
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 01967ddeef53..be4ab3d73c91 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -77,9 +77,8 @@ no_pmd: | |||
77 | } | 77 | } |
78 | 78 | ||
79 | static void | 79 | static void |
80 | make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty) | 80 | make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) |
81 | { | 81 | { |
82 | struct address_space *mapping = page_mapping(page); | ||
83 | struct mm_struct *mm = vma->vm_mm; | 82 | struct mm_struct *mm = vma->vm_mm; |
84 | struct vm_area_struct *mpnt; | 83 | struct vm_area_struct *mpnt; |
85 | struct prio_tree_iter iter; | 84 | struct prio_tree_iter iter; |
@@ -87,9 +86,6 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, | |||
87 | pgoff_t pgoff; | 86 | pgoff_t pgoff; |
88 | int aliases = 0; | 87 | int aliases = 0; |
89 | 88 | ||
90 | if (!mapping) | ||
91 | return; | ||
92 | |||
93 | pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT); | 89 | pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT); |
94 | 90 | ||
95 | /* | 91 | /* |
@@ -115,9 +111,11 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, | |||
115 | if (aliases) | 111 | if (aliases) |
116 | adjust_pte(vma, addr); | 112 | adjust_pte(vma, addr); |
117 | else | 113 | else |
118 | flush_cache_page(vma, addr, page_to_pfn(page)); | 114 | flush_cache_page(vma, addr, pfn); |
119 | } | 115 | } |
120 | 116 | ||
117 | void __flush_dcache_page(struct address_space *mapping, struct page *page); | ||
118 | |||
121 | /* | 119 | /* |
122 | * Take care of architecture specific things when placing a new PTE into | 120 | * Take care of architecture specific things when placing a new PTE into |
123 | * a page table, or changing an existing PTE. Basically, there are two | 121 | * 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, | |||
134 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) | 132 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) |
135 | { | 133 | { |
136 | unsigned long pfn = pte_pfn(pte); | 134 | unsigned long pfn = pte_pfn(pte); |
135 | struct address_space *mapping; | ||
137 | struct page *page; | 136 | struct page *page; |
138 | 137 | ||
139 | if (!pfn_valid(pfn)) | 138 | if (!pfn_valid(pfn)) |
140 | return; | 139 | return; |
140 | |||
141 | page = pfn_to_page(pfn); | 141 | page = pfn_to_page(pfn); |
142 | if (page_mapping(page)) { | 142 | mapping = page_mapping(page); |
143 | if (mapping) { | ||
143 | int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); | 144 | int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); |
144 | 145 | ||
145 | if (dirty) { | 146 | if (dirty) |
146 | /* | 147 | __flush_dcache_page(mapping, page); |
147 | * This is our first userspace mapping of this page. | ||
148 | * Ensure that the physical page is coherent with | ||
149 | * the kernel mapping. | ||
150 | * | ||
151 | * FIXME: only need to do this on VIVT and aliasing | ||
152 | * VIPT cache architectures. We can do that | ||
153 | * by choosing whether to set this bit... | ||
154 | */ | ||
155 | __cpuc_flush_dcache_page(page_address(page)); | ||
156 | } | ||
157 | 148 | ||
158 | if (cache_is_vivt()) | 149 | if (cache_is_vivt()) |
159 | make_coherent(vma, addr, page, dirty); | 150 | make_coherent(mapping, vma, addr, pfn); |
160 | } | 151 | } |
161 | } | 152 | } |
162 | 153 | ||
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 4085ed983e46..191788fb18d1 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -37,13 +37,8 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) | |||
37 | #define flush_pfn_alias(pfn,vaddr) do { } while (0) | 37 | #define flush_pfn_alias(pfn,vaddr) do { } while (0) |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | static void __flush_dcache_page(struct address_space *mapping, struct page *page) | 40 | void __flush_dcache_page(struct address_space *mapping, struct page *page) |
41 | { | 41 | { |
42 | struct mm_struct *mm = current->active_mm; | ||
43 | struct vm_area_struct *mpnt; | ||
44 | struct prio_tree_iter iter; | ||
45 | pgoff_t pgoff; | ||
46 | |||
47 | /* | 42 | /* |
48 | * Writeback any data associated with the kernel mapping of this | 43 | * Writeback any data associated with the kernel mapping of this |
49 | * page. This ensures that data in the physical page is mutually | 44 | * 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 | |||
52 | __cpuc_flush_dcache_page(page_address(page)); | 47 | __cpuc_flush_dcache_page(page_address(page)); |
53 | 48 | ||
54 | /* | 49 | /* |
55 | * If there's no mapping pointer here, then this page isn't | 50 | * If this is a page cache page, and we have an aliasing VIPT cache, |
56 | * visible to userspace yet, so there are no cache lines | 51 | * we only need to do one flush - which would be at the relevant |
57 | * associated with any other aliases. | ||
58 | */ | ||
59 | if (!mapping) | ||
60 | return; | ||
61 | |||
62 | /* | ||
63 | * This is a page cache page. If we have a VIPT cache, we | ||
64 | * only need to do one flush - which would be at the relevant | ||
65 | * userspace colour, which is congruent with page->index. | 52 | * userspace colour, which is congruent with page->index. |
66 | */ | 53 | */ |
67 | if (cache_is_vipt()) { | 54 | if (mapping && cache_is_vipt_aliasing()) |
68 | if (cache_is_vipt_aliasing()) | 55 | flush_pfn_alias(page_to_pfn(page), |
69 | flush_pfn_alias(page_to_pfn(page), | 56 | page->index << PAGE_CACHE_SHIFT); |
70 | page->index << PAGE_CACHE_SHIFT); | 57 | } |
71 | return; | 58 | |
72 | } | 59 | static void __flush_dcache_aliases(struct address_space *mapping, struct page *page) |
60 | { | ||
61 | struct mm_struct *mm = current->active_mm; | ||
62 | struct vm_area_struct *mpnt; | ||
63 | struct prio_tree_iter iter; | ||
64 | pgoff_t pgoff; | ||
73 | 65 | ||
74 | /* | 66 | /* |
75 | * There are possible user space mappings of this page: | 67 | * There are possible user space mappings of this page: |
@@ -116,12 +108,12 @@ void flush_dcache_page(struct page *page) | |||
116 | { | 108 | { |
117 | struct address_space *mapping = page_mapping(page); | 109 | struct address_space *mapping = page_mapping(page); |
118 | 110 | ||
119 | if (cache_is_vipt_nonaliasing()) | ||
120 | return; | ||
121 | |||
122 | if (mapping && !mapping_mapped(mapping)) | 111 | if (mapping && !mapping_mapped(mapping)) |
123 | set_bit(PG_dcache_dirty, &page->flags); | 112 | set_bit(PG_dcache_dirty, &page->flags); |
124 | else | 113 | else { |
125 | __flush_dcache_page(mapping, page); | 114 | __flush_dcache_page(mapping, page); |
115 | if (mapping && cache_is_vivt()) | ||
116 | __flush_dcache_aliases(mapping, page); | ||
117 | } | ||
126 | } | 118 | } |
127 | EXPORT_SYMBOL(flush_dcache_page); | 119 | EXPORT_SYMBOL(flush_dcache_page); |
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 00bb8fd37a59..7110e54182b1 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
@@ -170,3 +170,50 @@ void __iounmap(void __iomem *addr) | |||
170 | vfree((void *) (PAGE_MASK & (unsigned long) addr)); | 170 | vfree((void *) (PAGE_MASK & (unsigned long) addr)); |
171 | } | 171 | } |
172 | EXPORT_SYMBOL(__iounmap); | 172 | EXPORT_SYMBOL(__iounmap); |
173 | |||
174 | #ifdef __io | ||
175 | void __iomem *ioport_map(unsigned long port, unsigned int nr) | ||
176 | { | ||
177 | return __io(port); | ||
178 | } | ||
179 | EXPORT_SYMBOL(ioport_map); | ||
180 | |||
181 | void ioport_unmap(void __iomem *addr) | ||
182 | { | ||
183 | } | ||
184 | EXPORT_SYMBOL(ioport_unmap); | ||
185 | #endif | ||
186 | |||
187 | #ifdef CONFIG_PCI | ||
188 | #include <linux/pci.h> | ||
189 | #include <linux/ioport.h> | ||
190 | |||
191 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | ||
192 | { | ||
193 | unsigned long start = pci_resource_start(dev, bar); | ||
194 | unsigned long len = pci_resource_len(dev, bar); | ||
195 | unsigned long flags = pci_resource_flags(dev, bar); | ||
196 | |||
197 | if (!len || !start) | ||
198 | return NULL; | ||
199 | if (maxlen && len > maxlen) | ||
200 | len = maxlen; | ||
201 | if (flags & IORESOURCE_IO) | ||
202 | return ioport_map(start, len); | ||
203 | if (flags & IORESOURCE_MEM) { | ||
204 | if (flags & IORESOURCE_CACHEABLE) | ||
205 | return ioremap(start, len); | ||
206 | return ioremap_nocache(start, len); | ||
207 | } | ||
208 | return NULL; | ||
209 | } | ||
210 | EXPORT_SYMBOL(pci_iomap); | ||
211 | |||
212 | void pci_iounmap(struct pci_dev *dev, void __iomem *addr) | ||
213 | { | ||
214 | if ((unsigned long)addr >= VMALLOC_START && | ||
215 | (unsigned long)addr < VMALLOC_END) | ||
216 | iounmap(addr); | ||
217 | } | ||
218 | EXPORT_SYMBOL(pci_iounmap); | ||
219 | #endif | ||
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c index 344164681d2c..8316426ccaf6 100644 --- a/arch/ppc64/kernel/iommu.c +++ b/arch/ppc64/kernel/iommu.c | |||
@@ -423,6 +423,9 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl) | |||
423 | tbl->it_largehint = tbl->it_halfpoint; | 423 | tbl->it_largehint = tbl->it_halfpoint; |
424 | spin_lock_init(&tbl->it_lock); | 424 | spin_lock_init(&tbl->it_lock); |
425 | 425 | ||
426 | /* Clear the hardware table in case firmware left allocations in it */ | ||
427 | ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); | ||
428 | |||
426 | if (!welcomed) { | 429 | if (!welcomed) { |
427 | printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", | 430 | printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", |
428 | novmerge ? "disabled" : "enabled"); | 431 | novmerge ? "disabled" : "enabled"); |
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c index fbad349ec58c..4203bd020c82 100644 --- a/arch/ppc64/kernel/pSeries_smp.c +++ b/arch/ppc64/kernel/pSeries_smp.c | |||
@@ -375,7 +375,7 @@ static int smp_pSeries_cpu_bootable(unsigned int nr) | |||
375 | * cpus are assumed to be secondary threads. | 375 | * cpus are assumed to be secondary threads. |
376 | */ | 376 | */ |
377 | if (system_state < SYSTEM_RUNNING && | 377 | if (system_state < SYSTEM_RUNNING && |
378 | cur_cpu_spec->cpu_features & CPU_FTR_SMT && | 378 | cpu_has_feature(CPU_FTR_SMT) && |
379 | !smt_enabled_at_boot && nr % 2 != 0) | 379 | !smt_enabled_at_boot && nr % 2 != 0) |
380 | return 0; | 380 | return 0; |
381 | 381 | ||
@@ -419,8 +419,8 @@ void __init smp_init_pSeries(void) | |||
419 | #endif | 419 | #endif |
420 | 420 | ||
421 | /* Mark threads which are still spinning in hold loops. */ | 421 | /* Mark threads which are still spinning in hold loops. */ |
422 | if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) | 422 | if (cpu_has_feature(CPU_FTR_SMT)) { |
423 | for_each_present_cpu(i) { | 423 | for_each_present_cpu(i) { |
424 | if (i % 2 == 0) | 424 | if (i % 2 == 0) |
425 | /* | 425 | /* |
426 | * Even-numbered logical cpus correspond to | 426 | * Even-numbered logical cpus correspond to |
@@ -428,8 +428,9 @@ void __init smp_init_pSeries(void) | |||
428 | */ | 428 | */ |
429 | cpu_set(i, of_spin_map); | 429 | cpu_set(i, of_spin_map); |
430 | } | 430 | } |
431 | else | 431 | } else { |
432 | of_spin_map = cpu_present_map; | 432 | of_spin_map = cpu_present_map; |
433 | } | ||
433 | 434 | ||
434 | cpu_clear(boot_cpuid, of_spin_map); | 435 | cpu_clear(boot_cpuid, of_spin_map); |
435 | 436 | ||
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c index ff65dc33320e..b0c3b829fe47 100644 --- a/arch/ppc64/kernel/rtasd.c +++ b/arch/ppc64/kernel/rtasd.c | |||
@@ -440,7 +440,7 @@ static int rtasd(void *unused) | |||
440 | goto error; | 440 | goto error; |
441 | } | 441 | } |
442 | 442 | ||
443 | printk(KERN_ERR "RTAS daemon started\n"); | 443 | printk(KERN_INFO "RTAS daemon started\n"); |
444 | 444 | ||
445 | DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2); | 445 | DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2); |
446 | 446 | ||
@@ -485,7 +485,7 @@ static int __init rtas_init(void) | |||
485 | /* No RTAS, only warn if we are on a pSeries box */ | 485 | /* No RTAS, only warn if we are on a pSeries box */ |
486 | if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { | 486 | if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { |
487 | if (systemcfg->platform & PLATFORM_PSERIES) | 487 | if (systemcfg->platform & PLATFORM_PSERIES) |
488 | printk(KERN_ERR "rtasd: no event-scan on system\n"); | 488 | printk(KERN_INFO "rtasd: no event-scan on system\n"); |
489 | return 1; | 489 | return 1; |
490 | } | 490 | } |
491 | 491 | ||
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c index ab659d37b4d2..4e98c215e5b1 100644 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ b/drivers/char/watchdog/ixp2000_wdt.c | |||
@@ -192,7 +192,12 @@ static struct miscdevice ixp2000_wdt_miscdev = | |||
192 | 192 | ||
193 | static int __init ixp2000_wdt_init(void) | 193 | static int __init ixp2000_wdt_init(void) |
194 | { | 194 | { |
195 | wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;; | 195 | if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) { |
196 | printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n"); | ||
197 | return -EIO; | ||
198 | } | ||
199 | |||
200 | wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; | ||
196 | 201 | ||
197 | return misc_register(&ixp2000_wdt_miscdev); | 202 | return misc_register(&ixp2000_wdt_miscdev); |
198 | } | 203 | } |
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index fbd9ff79b7b8..e3c958823533 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c | |||
@@ -765,8 +765,6 @@ void fcp_release(fc_channel *fcchain, int count) /* count must > 0 */ | |||
765 | 765 | ||
766 | static void fcp_scsi_done (Scsi_Cmnd *SCpnt) | 766 | static void fcp_scsi_done (Scsi_Cmnd *SCpnt) |
767 | { | 767 | { |
768 | unsigned long flags; | ||
769 | |||
770 | if (FCP_CMND(SCpnt)->done) | 768 | if (FCP_CMND(SCpnt)->done) |
771 | FCP_CMND(SCpnt)->done(SCpnt); | 769 | FCP_CMND(SCpnt)->done(SCpnt); |
772 | } | 770 | } |
@@ -907,8 +905,6 @@ int fcp_scsi_abort(Scsi_Cmnd *SCpnt) | |||
907 | */ | 905 | */ |
908 | 906 | ||
909 | if (++fc->abort_count < (fc->can_queue >> 1)) { | 907 | if (++fc->abort_count < (fc->can_queue >> 1)) { |
910 | unsigned long flags; | ||
911 | |||
912 | SCpnt->result = DID_ABORT; | 908 | SCpnt->result = DID_ABORT; |
913 | fcmd->done(SCpnt); | 909 | fcmd->done(SCpnt); |
914 | printk("FC: soft abort\n"); | 910 | printk("FC: soft abort\n"); |
@@ -931,6 +927,7 @@ void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt) | |||
931 | 927 | ||
932 | int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) | 928 | int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) |
933 | { | 929 | { |
930 | unsigned long flags; | ||
934 | fcp_cmd *cmd; | 931 | fcp_cmd *cmd; |
935 | fcp_cmnd *fcmd; | 932 | fcp_cmnd *fcmd; |
936 | fc_channel *fc = FC_SCMND(SCpnt); | 933 | fc_channel *fc = FC_SCMND(SCpnt); |
@@ -1028,6 +1025,7 @@ static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) | |||
1028 | 1025 | ||
1029 | int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) | 1026 | int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) |
1030 | { | 1027 | { |
1028 | unsigned long flags; | ||
1031 | int rc; | 1029 | int rc; |
1032 | 1030 | ||
1033 | spin_lock_irqsave(SCpnt->device->host->host_lock, flags); | 1031 | spin_lock_irqsave(SCpnt->device->host->host_lock, flags); |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index c4eaaad2c69b..5f526dd0aaa1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -941,7 +941,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) | |||
941 | */ | 941 | */ |
942 | cmd->scsi_done = scsi_done; | 942 | cmd->scsi_done = scsi_done; |
943 | 943 | ||
944 | ahd_lock(ahd, &flags); | 944 | ahd_midlayer_entrypoint_lock(ahd, &flags); |
945 | 945 | ||
946 | /* | 946 | /* |
947 | * Close the race of a command that was in the process of | 947 | * 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 *)) | |||
955 | ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); | 955 | ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); |
956 | ahd_linux_queue_cmd_complete(ahd, cmd); | 956 | ahd_linux_queue_cmd_complete(ahd, cmd); |
957 | ahd_schedule_completeq(ahd); | 957 | ahd_schedule_completeq(ahd); |
958 | ahd_unlock(ahd, &flags); | 958 | ahd_midlayer_entrypoint_unlock(ahd, &flags); |
959 | return (0); | 959 | return (0); |
960 | } | 960 | } |
961 | dev = ahd_linux_get_device(ahd, cmd->device->channel, | 961 | dev = ahd_linux_get_device(ahd, cmd->device->channel, |
@@ -965,7 +965,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) | |||
965 | ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); | 965 | ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); |
966 | ahd_linux_queue_cmd_complete(ahd, cmd); | 966 | ahd_linux_queue_cmd_complete(ahd, cmd); |
967 | ahd_schedule_completeq(ahd); | 967 | ahd_schedule_completeq(ahd); |
968 | ahd_unlock(ahd, &flags); | 968 | ahd_midlayer_entrypoint_unlock(ahd, &flags); |
969 | printf("%s: aic79xx_linux_queue - Unable to allocate device!\n", | 969 | printf("%s: aic79xx_linux_queue - Unable to allocate device!\n", |
970 | ahd_name(ahd)); | 970 | ahd_name(ahd)); |
971 | return (0); | 971 | return (0); |
@@ -979,7 +979,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) | |||
979 | dev->flags |= AHD_DEV_ON_RUN_LIST; | 979 | dev->flags |= AHD_DEV_ON_RUN_LIST; |
980 | ahd_linux_run_device_queues(ahd); | 980 | ahd_linux_run_device_queues(ahd); |
981 | } | 981 | } |
982 | ahd_unlock(ahd, &flags); | 982 | ahd_midlayer_entrypoint_unlock(ahd, &flags); |
983 | return (0); | 983 | return (0); |
984 | } | 984 | } |
985 | 985 | ||
diff --git a/include/asm-arm/arch-aaec2000/aaec2000.h b/include/asm-arm/arch-aaec2000/aaec2000.h new file mode 100644 index 000000000000..0e9b7e18af05 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/aaec2000.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/aaec2000.h | ||
3 | * | ||
4 | * AAEC-2000 registers definition | ||
5 | * | ||
6 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_AAEC2000_H | ||
14 | #define __ASM_ARCH_AAEC2000_H | ||
15 | |||
16 | #ifndef __ASM_ARCH_HARDWARE_H | ||
17 | #error You must include hardware.h not this file | ||
18 | #endif /* __ASM_ARCH_HARDWARE_H */ | ||
19 | |||
20 | /* Interrupt controller */ | ||
21 | #define IRQ_BASE __REG(0x80000500) | ||
22 | #define IRQ_INTSR __REG(0x80000500) /* Int Status Register */ | ||
23 | #define IRQ_INTRSR __REG(0x80000504) /* Int Raw (unmasked) Status */ | ||
24 | #define IRQ_INTENS __REG(0x80000508) /* Int Enable Set */ | ||
25 | #define IRQ_INTENC __REG(0x8000050c) /* Int Enable Clear */ | ||
26 | |||
27 | /* UART 1 */ | ||
28 | #define UART1_BASE __REG(0x80000600) | ||
29 | #define UART1_DR __REG(0x80000600) /* Data/FIFO Register */ | ||
30 | #define UART1_LCR __REG(0x80000604) /* Link Control Register */ | ||
31 | #define UART1_BRCR __REG(0x80000608) /* Baud Rate Control Register */ | ||
32 | #define UART1_CR __REG(0x8000060c) /* Control Register */ | ||
33 | #define UART1_SR __REG(0x80000610) /* Status Register */ | ||
34 | #define UART1_INT __REG(0x80000614) /* Interrupt Status Register */ | ||
35 | #define UART1_INTM __REG(0x80000618) /* Interrupt Mask Register */ | ||
36 | #define UART1_INTRES __REG(0x8000061c) /* Int Result (masked status) Register */ | ||
37 | |||
38 | /* UART 2 */ | ||
39 | #define UART2_BASE __REG(0x80000700) | ||
40 | #define UART2_DR __REG(0x80000700) /* Data/FIFO Register */ | ||
41 | #define UART2_LCR __REG(0x80000704) /* Link Control Register */ | ||
42 | #define UART2_BRCR __REG(0x80000708) /* Baud Rate Control Register */ | ||
43 | #define UART2_CR __REG(0x8000070c) /* Control Register */ | ||
44 | #define UART2_SR __REG(0x80000710) /* Status Register */ | ||
45 | #define UART2_INT __REG(0x80000714) /* Interrupt Status Register */ | ||
46 | #define UART2_INTM __REG(0x80000718) /* Interrupt Mask Register */ | ||
47 | #define UART2_INTRES __REG(0x8000071c) /* Int Result (masked status) Register */ | ||
48 | |||
49 | /* UART 3 */ | ||
50 | #define UART3_BASE __REG(0x80000800) | ||
51 | #define UART3_DR __REG(0x80000800) /* Data/FIFO Register */ | ||
52 | #define UART3_LCR __REG(0x80000804) /* Link Control Register */ | ||
53 | #define UART3_BRCR __REG(0x80000808) /* Baud Rate Control Register */ | ||
54 | #define UART3_CR __REG(0x8000080c) /* Control Register */ | ||
55 | #define UART3_SR __REG(0x80000810) /* Status Register */ | ||
56 | #define UART3_INT __REG(0x80000814) /* Interrupt Status Register */ | ||
57 | #define UART3_INTM __REG(0x80000818) /* Interrupt Mask Register */ | ||
58 | #define UART3_INTRES __REG(0x8000081c) /* Int Result (masked status) Register */ | ||
59 | |||
60 | /* These are used in some places */ | ||
61 | #define _UART1_BASE __PREG(UART1_BASE) | ||
62 | #define _UART2_BASE __PREG(UART2_BASE) | ||
63 | #define _UART3_BASE __PREG(UART3_BASE) | ||
64 | |||
65 | /* UART Registers Offsets */ | ||
66 | #define UART_DR 0x00 | ||
67 | #define UART_LCR 0x04 | ||
68 | #define UART_BRCR 0x08 | ||
69 | #define UART_CR 0x0c | ||
70 | #define UART_SR 0x10 | ||
71 | #define UART_INT 0x14 | ||
72 | #define UART_INTM 0x18 | ||
73 | #define UART_INTRES 0x1c | ||
74 | |||
75 | /* UART_LCR Bitmask */ | ||
76 | #define UART_LCR_BRK (1 << 0) /* Send Break */ | ||
77 | #define UART_LCR_PEN (1 << 1) /* Parity Enable */ | ||
78 | #define UART_LCR_EP (1 << 2) /* Even/Odd Parity */ | ||
79 | #define UART_LCR_S2 (1 << 3) /* One/Two Stop bits */ | ||
80 | #define UART_LCR_FIFO (1 << 4) /* FIFO Enable */ | ||
81 | #define UART_LCR_WL5 (0 << 5) /* Word Length - 5 bits */ | ||
82 | #define UART_LCR_WL6 (1 << 5) /* Word Length - 6 bits */ | ||
83 | #define UART_LCR_WL7 (1 << 6) /* Word Length - 7 bits */ | ||
84 | #define UART_LCR_WL8 (1 << 7) /* Word Length - 8 bits */ | ||
85 | |||
86 | /* UART_CR Bitmask */ | ||
87 | #define UART_CR_EN (1 << 0) /* UART Enable */ | ||
88 | #define UART_CR_SIR (1 << 1) /* IrDA SIR Enable */ | ||
89 | #define UART_CR_SIRLP (1 << 2) /* Low Power IrDA Enable */ | ||
90 | #define UART_CR_RXP (1 << 3) /* Receive Pin Polarity */ | ||
91 | #define UART_CR_TXP (1 << 4) /* Transmit Pin Polarity */ | ||
92 | #define UART_CR_MXP (1 << 5) /* Modem Pin Polarity */ | ||
93 | #define UART_CR_LOOP (1 << 6) /* Loopback Mode */ | ||
94 | |||
95 | /* UART_SR Bitmask */ | ||
96 | #define UART_SR_CTS (1 << 0) /* Clear To Send Status */ | ||
97 | #define UART_SR_DSR (1 << 1) /* Data Set Ready Status */ | ||
98 | #define UART_SR_DCD (1 << 2) /* Data Carrier Detect Status */ | ||
99 | #define UART_SR_TxBSY (1 << 3) /* Transmitter Busy Status */ | ||
100 | #define UART_SR_RxFE (1 << 4) /* Receive FIFO Empty Status */ | ||
101 | #define UART_SR_TxFF (1 << 5) /* Transmit FIFO Full Status */ | ||
102 | #define UART_SR_RxFF (1 << 6) /* Receive FIFO Full Status */ | ||
103 | #define UART_SR_TxFE (1 << 7) /* Transmit FIFO Empty Status */ | ||
104 | |||
105 | /* UART_INT Bitmask */ | ||
106 | #define UART_INT_RIS (1 << 0) /* Rx Interrupt */ | ||
107 | #define UART_INT_TIS (1 << 1) /* Tx Interrupt */ | ||
108 | #define UART_INT_MIS (1 << 2) /* Modem Interrupt */ | ||
109 | #define UART_INT_RTIS (1 << 3) /* Receive Timeout Interrupt */ | ||
110 | |||
111 | /* Timer 1 */ | ||
112 | #define TIMER1_BASE __REG(0x80000c00) | ||
113 | #define TIMER1_LOAD __REG(0x80000c00) /* Timer 1 Load Register */ | ||
114 | #define TIMER1_VAL __REG(0x80000c04) /* Timer 1 Value Register */ | ||
115 | #define TIMER1_CTRL __REG(0x80000c08) /* Timer 1 Control Register */ | ||
116 | #define TIMER1_CLEAR __REG(0x80000c0c) /* Timer 1 Clear Register */ | ||
117 | |||
118 | /* Timer 2 */ | ||
119 | #define TIMER2_BASE __REG(0x80000d00) | ||
120 | #define TIMER2_LOAD __REG(0x80000d00) /* Timer 2 Load Register */ | ||
121 | #define TIMER2_VAL __REG(0x80000d04) /* Timer 2 Value Register */ | ||
122 | #define TIMER2_CTRL __REG(0x80000d08) /* Timer 2 Control Register */ | ||
123 | #define TIMER2_CLEAR __REG(0x80000d0c) /* Timer 2 Clear Register */ | ||
124 | |||
125 | /* Timer 3 */ | ||
126 | #define TIMER3_BASE __REG(0x80000e00) | ||
127 | #define TIMER3_LOAD __REG(0x80000e00) /* Timer 3 Load Register */ | ||
128 | #define TIMER3_VAL __REG(0x80000e04) /* Timer 3 Value Register */ | ||
129 | #define TIMER3_CTRL __REG(0x80000e08) /* Timer 3 Control Register */ | ||
130 | #define TIMER3_CLEAR __REG(0x80000e0c) /* Timer 3 Clear Register */ | ||
131 | |||
132 | /* Timer Control register bits */ | ||
133 | #define TIMER_CTRL_ENABLE (1 << 7) /* Enable (Start° Timer */ | ||
134 | #define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic Running Mode */ | ||
135 | #define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */ | ||
136 | #define TIMER_CTRL_CLKSEL_508K (1 << 3) /* 508KHz Clock select (Timer 1, 2) */ | ||
137 | #define TIMER_CTRL_CLKSEL_2K (0 << 3) /* 2KHz Clock Select (Timer 1, 2)*/ | ||
138 | |||
139 | /* Power and State Control */ | ||
140 | #define POWER_BASE __REG(0x80000400) | ||
141 | #define POWER_PWRSR __REG(0x80000400) /* Power Status Register */ | ||
142 | #define POWER_PWRCNT __REG(0x80000404) /* Power/Clock control */ | ||
143 | #define POWER_HALT __REG(0x80000408) /* Power Idle Mode */ | ||
144 | #define POWER_STDBY __REG(0x8000040c) /* Power Standby Mode */ | ||
145 | #define POWER_BLEOI __REG(0x80000410) /* Battery Low End of Interrupt */ | ||
146 | #define POWER_MCEOI __REG(0x80000414) /* Media Changed EoI */ | ||
147 | #define POWER_TEOI __REG(0x80000418) /* Tick EoI */ | ||
148 | #define POWER_STFCLR __REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */ | ||
149 | #define POWER_CLKSET __REG(0x80000420) /* Clock Speed Control */ | ||
150 | |||
151 | #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 index 000000000000..e4f1fa539a74 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/debug-macro.S | |||
@@ -0,0 +1,36 @@ | |||
1 | /* linux/include/asm-arm/arch-aaec2000/debug-macro.S | ||
2 | * | ||
3 | * Debugging macro include header | ||
4 | * | ||
5 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | .macro addruart,rx | ||
13 | mrc p15, 0, \rx, c1, c0 | ||
14 | tst \rx, #1 @ MMU enabled? | ||
15 | moveq \rx, #0x80000000 @ physical | ||
16 | movne \rx, #io_p2v(0x80000000) @ virtual | ||
17 | orr \rx, \rx, #0x00000800 | ||
18 | .endm | ||
19 | |||
20 | .macro senduart,rd,rx | ||
21 | str \rd, [\rx, #0] | ||
22 | .endm | ||
23 | |||
24 | .macro busyuart,rd,rx | ||
25 | 1002: ldr \rd, [\rx, #0x10] | ||
26 | tst \rd, #(1 << 7) | ||
27 | beq 1002b | ||
28 | .endm | ||
29 | |||
30 | .macro waituart,rd,rx | ||
31 | #if 0 | ||
32 | 1001: ldr \rd, [\rx, #0x10] | ||
33 | tst \rd, #(1 << 5) | ||
34 | beq 1001b | ||
35 | #endif | ||
36 | .endm | ||
diff --git a/include/asm-arm/arch-aaec2000/dma.h b/include/asm-arm/arch-aaec2000/dma.h new file mode 100644 index 000000000000..28c890b4a1d3 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/dma.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/dma.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_DMA_H | ||
12 | #define __ASM_ARCH_DMA_H | ||
13 | |||
14 | #define MAX_DMA_ADDRESS 0xffffffff | ||
15 | #define MAX_DMA_CHANNELS 0 | ||
16 | |||
17 | #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 index 000000000000..df31313ab07e --- /dev/null +++ b/include/asm-arm/arch-aaec2000/entry-macro.S | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/entry-macro.S | ||
3 | * | ||
4 | * Low-level IRQ helper for aaec-2000 based platforms | ||
5 | * | ||
6 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | .macro disable_fiq | ||
15 | .endm | ||
16 | |||
17 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
18 | mov r4, #0xf8000000 | ||
19 | add r4, r4, #0x00000500 | ||
20 | mov \base, r4 | ||
21 | ldr \irqstat, [\base, #0] | ||
22 | cmp \irqstat, #0 | ||
23 | bne 1001f | ||
24 | ldr \irqnr, =NR_IRQS+1 | ||
25 | b 1003f | ||
26 | 1001: mov \irqnr, #0 | ||
27 | 1002: ands \tmp, \irqstat, #1 | ||
28 | mov \irqstat, \irqstat, LSR #1 | ||
29 | add \irqnr, \irqnr, #1 | ||
30 | beq 1002b | ||
31 | sub \irqnr, \irqnr, #1 | ||
32 | 1003: | ||
33 | .endm | ||
diff --git a/include/asm-arm/arch-aaec2000/hardware.h b/include/asm-arm/arch-aaec2000/hardware.h new file mode 100644 index 000000000000..4c37219e030e --- /dev/null +++ b/include/asm-arm/arch-aaec2000/hardware.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/hardware.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_HARDWARE_H | ||
12 | #define __ASM_ARCH_HARDWARE_H | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | |||
16 | /* The kernel is loaded at physical address 0xf8000000. | ||
17 | * We map the IO space a bit after | ||
18 | */ | ||
19 | #define PIO_APB_BASE 0x80000000 | ||
20 | #define VIO_APB_BASE 0xf8000000 | ||
21 | #define IO_APB_LENGTH 0x2000 | ||
22 | #define PIO_AHB_BASE 0x80002000 | ||
23 | #define VIO_AHB_BASE 0xf8002000 | ||
24 | #define IO_AHB_LENGTH 0x2000 | ||
25 | |||
26 | #define VIO_BASE VIO_APB_BASE | ||
27 | #define PIO_BASE PIO_APB_BASE | ||
28 | |||
29 | #define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE ) | ||
30 | #define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE ) | ||
31 | |||
32 | #ifndef __ASSEMBLY__ | ||
33 | |||
34 | #include <asm/types.h> | ||
35 | |||
36 | /* FIXME: Is it needed to optimize this a la pxa ?? */ | ||
37 | #define __REG(x) (*((volatile u32 *)io_p2v(x))) | ||
38 | #define __PREG(x) (io_v2p((u32)&(x))) | ||
39 | |||
40 | #else /* __ASSEMBLY__ */ | ||
41 | |||
42 | #define __REG(x) io_p2v(x) | ||
43 | #define __PREG(x) io_v2p(x) | ||
44 | |||
45 | #endif | ||
46 | |||
47 | #include "aaec2000.h" | ||
48 | |||
49 | #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 index 000000000000..c58a8d10425a --- /dev/null +++ b/include/asm-arm/arch-aaec2000/io.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/io.h | ||
3 | * | ||
4 | * Copied from asm/arch/sa1100/io.h | ||
5 | */ | ||
6 | #ifndef __ASM_ARM_ARCH_IO_H | ||
7 | #define __ASM_ARM_ARCH_IO_H | ||
8 | |||
9 | #define IO_SPACE_LIMIT 0xffffffff | ||
10 | |||
11 | /* | ||
12 | * We don't actually have real ISA nor PCI buses, but there is so many | ||
13 | * drivers out there that might just work if we fake them... | ||
14 | */ | ||
15 | #define __io(a) ((void __iomem *)(a)) | ||
16 | #define __mem_pci(a) (a) | ||
17 | #define __mem_isa(a) (a) | ||
18 | |||
19 | #endif | ||
diff --git a/include/asm-arm/arch-aaec2000/irqs.h b/include/asm-arm/arch-aaec2000/irqs.h new file mode 100644 index 000000000000..de252220e806 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/irqs.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/irqs.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_IRQS_H | ||
12 | #define __ASM_ARCH_IRQS_H | ||
13 | |||
14 | |||
15 | #define INT_GPIOF0_FIQ 0 /* External GPIO Port F O Fast Interrupt Input */ | ||
16 | #define INT_BL_FIQ 1 /* Battery Low Fast Interrupt */ | ||
17 | #define INT_WE_FIQ 2 /* Watchdog Expired Fast Interrupt */ | ||
18 | #define INT_MV_FIQ 3 /* Media Changed Interrupt */ | ||
19 | #define INT_SC 4 /* Sound Codec Interrupt */ | ||
20 | #define INT_GPIO1 5 /* GPIO Port F Configurable Int 1 */ | ||
21 | #define INT_GPIO2 6 /* GPIO Port F Configurable Int 2 */ | ||
22 | #define INT_GPIO3 7 /* GPIO Port F Configurable Int 3 */ | ||
23 | #define INT_TMR1_OFL 8 /* Timer 1 Overflow Interrupt */ | ||
24 | #define INT_TMR2_OFL 9 /* Timer 2 Overflow Interrupt */ | ||
25 | #define INT_RTC_CM 10 /* RTC Compare Match Interrupt */ | ||
26 | #define INT_TICK 11 /* 64Hz Tick Interrupt */ | ||
27 | #define INT_UART1 12 /* UART1 Interrupt */ | ||
28 | #define INT_UART2 13 /* UART2 & Modem State Changed Interrupt */ | ||
29 | #define INT_LCD 14 /* LCD Interrupt */ | ||
30 | #define INT_SSI 15 /* SSI End of Transfer Interrupt */ | ||
31 | #define INT_UART3 16 /* UART3 Interrupt */ | ||
32 | #define INT_SCI 17 /* SCI Interrupt */ | ||
33 | #define INT_AAC 18 /* Advanced Audio Codec Interrupt */ | ||
34 | #define INT_MMC 19 /* MMC Interrupt */ | ||
35 | #define INT_USB 20 /* USB Interrupt */ | ||
36 | #define INT_DMA 21 /* DMA Interrupt */ | ||
37 | #define INT_TMR3_UOFL 22 /* Timer 3 Underflow Interrupt */ | ||
38 | #define INT_GPIO4 23 /* GPIO Port F Configurable Int 4 */ | ||
39 | #define INT_GPIO5 24 /* GPIO Port F Configurable Int 4 */ | ||
40 | #define INT_GPIO6 25 /* GPIO Port F Configurable Int 4 */ | ||
41 | #define INT_GPIO7 26 /* GPIO Port F Configurable Int 4 */ | ||
42 | #define INT_BMI 27 /* BMI Interrupt */ | ||
43 | |||
44 | #define NR_IRQS (INT_BMI + 1) | ||
45 | |||
46 | #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 index 000000000000..681b6a6171a1 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/memory.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/memory.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_MEMORY_H | ||
12 | #define __ASM_ARCH_MEMORY_H | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | |||
16 | #define PHYS_OFFSET (0xf0000000UL) | ||
17 | |||
18 | #define __virt_to_bus(x) __virt_to_phys(x) | ||
19 | #define __bus_to_virt(x) __phys_to_virt(x) | ||
20 | |||
21 | #ifdef CONFIG_DISCONTIGMEM | ||
22 | |||
23 | /* | ||
24 | * The nodes are the followings: | ||
25 | * | ||
26 | * node 0: 0xf000.0000 - 0xf3ff.ffff | ||
27 | * node 1: 0xf400.0000 - 0xf7ff.ffff | ||
28 | * node 2: 0xf800.0000 - 0xfbff.ffff | ||
29 | * node 3: 0xfc00.0000 - 0xffff.ffff | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * Given a kernel address, find the home node of the underlying memory. | ||
34 | */ | ||
35 | #define KVADDR_TO_NID(addr) \ | ||
36 | (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT) | ||
37 | |||
38 | /* | ||
39 | * Given a page frame number, convert it to a node id. | ||
40 | */ | ||
41 | #define PFN_TO_NID(pfn) \ | ||
42 | (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT)) | ||
43 | |||
44 | /* | ||
45 | * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory | ||
46 | * and return the mem_map of that node. | ||
47 | */ | ||
48 | #define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr)) | ||
49 | |||
50 | /* | ||
51 | * Given a page frame number, find the owning node of the memory | ||
52 | * and return the mem_map of that node. | ||
53 | */ | ||
54 | #define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) | ||
55 | |||
56 | /* | ||
57 | * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory | ||
58 | * and returns the index corresponding to the appropriate page in the | ||
59 | * node's mem_map. | ||
60 | */ | ||
61 | #define LOCAL_MAP_NR(addr) \ | ||
62 | (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT) | ||
63 | |||
64 | #define NODE_MAX_MEM_SHIFT 26 | ||
65 | #define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT) | ||
66 | |||
67 | #else | ||
68 | |||
69 | #define PFN_TO_NID(addr) (0) | ||
70 | |||
71 | #endif /* CONFIG_DISCONTIGMEM */ | ||
72 | |||
73 | #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 index 000000000000..139936c2faf2 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/param.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/param.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_PARAM_H | ||
12 | #define __ASM_ARCH_PARAM_H | ||
13 | |||
14 | #endif /* __ASM_ARCH_PARAM_H */ | ||
15 | |||
diff --git a/include/asm-arm/arch-aaec2000/system.h b/include/asm-arm/arch-aaec2000/system.h new file mode 100644 index 000000000000..08de97b407a8 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/system.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaed2000/system.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_SYSTEM_H | ||
12 | #define __ASM_ARCH_SYSTEM_H | ||
13 | |||
14 | static inline void arch_idle(void) | ||
15 | { | ||
16 | cpu_do_idle(); | ||
17 | } | ||
18 | |||
19 | static inline void arch_reset(char mode) | ||
20 | { | ||
21 | cpu_reset(0); | ||
22 | } | ||
23 | |||
24 | #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 index 000000000000..f5708b38fb7f --- /dev/null +++ b/include/asm-arm/arch-aaec2000/timex.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/timex.h | ||
3 | * | ||
4 | * AAEC-2000 Architecture timex specification | ||
5 | * | ||
6 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_TIMEX_H | ||
14 | #define __ASM_ARCH_TIMEX_H | ||
15 | |||
16 | #define CLOCK_TICK_RATE 508000 | ||
17 | |||
18 | #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 index 000000000000..fff0c94b75c4 --- /dev/null +++ b/include/asm-arm/arch-aaec2000/uncompress.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/uncompress.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_UNCOMPRESS_H | ||
12 | #define __ASM_ARCH_UNCOMPRESS_H | ||
13 | |||
14 | #include "hardware.h" | ||
15 | |||
16 | #define UART(x) (*(volatile unsigned long *)(serial_port + (x))) | ||
17 | |||
18 | static void putstr( const char *s ) | ||
19 | { | ||
20 | unsigned long serial_port; | ||
21 | do { | ||
22 | serial_port = _UART3_BASE; | ||
23 | if (UART(UART_CR) & UART_CR_EN) break; | ||
24 | serial_port = _UART1_BASE; | ||
25 | if (UART(UART_CR) & UART_CR_EN) break; | ||
26 | serial_port = _UART2_BASE; | ||
27 | if (UART(UART_CR) & UART_CR_EN) break; | ||
28 | return; | ||
29 | } while (0); | ||
30 | |||
31 | for (; *s; s++) { | ||
32 | /* wait for space in the UART's transmitter */ | ||
33 | while ((UART(UART_SR) & UART_SR_TxFF)); | ||
34 | /* send the character out. */ | ||
35 | UART(UART_DR) = *s; | ||
36 | /* if a LF, also do CR... */ | ||
37 | if (*s == 10) { | ||
38 | while ((UART(UART_SR) & UART_SR_TxFF)); | ||
39 | UART(UART_DR) = 13; | ||
40 | } | ||
41 | } | ||
42 | } | ||
43 | |||
44 | #define arch_decomp_setup() | ||
45 | #define arch_decomp_wdog() | ||
46 | |||
47 | #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 index 000000000000..ecb991e2e4ff --- /dev/null +++ b/include/asm-arm/arch-aaec2000/vmalloc.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-aaec2000/vmalloc.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_ARCH_VMALLOC_H | ||
12 | #define __ASM_ARCH_VMALLOC_H | ||
13 | |||
14 | #define VMALLOC_END (PAGE_OFFSET + 0x10000000) | ||
15 | |||
16 | #endif /* __ASM_ARCH_VMALLOC_H */ | ||
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h index 6c56708d0ff0..a1d9e181b10f 100644 --- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h +++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h | |||
@@ -363,6 +363,7 @@ | |||
363 | #define IXP2000_MIN_REV_MASK 0x0000000F | 363 | #define IXP2000_MIN_REV_MASK 0x0000000F |
364 | #define IXP2000_PROD_ID_MASK 0xFFFFFFFF | 364 | #define IXP2000_PROD_ID_MASK 0xFFFFFFFF |
365 | 365 | ||
366 | #define IXP2000_PRODUCT_ID GLOBAL_REG(0x00) | ||
366 | #define IXP2000_MISC_CONTROL GLOBAL_REG(0x04) | 367 | #define IXP2000_MISC_CONTROL GLOBAL_REG(0x04) |
367 | #define IXP2000_MSF_CLK_CNTRL GLOBAL_REG(0x08) | 368 | #define IXP2000_MSF_CLK_CNTRL GLOBAL_REG(0x08) |
368 | #define IXP2000_RESET0 GLOBAL_REG(0x0c) | 369 | #define IXP2000_RESET0 GLOBAL_REG(0x0c) |
diff --git a/include/asm-arm/arch-versatile/hardware.h b/include/asm-arm/arch-versatile/hardware.h index d5fb4a251e7f..41c1bee342ad 100644 --- a/include/asm-arm/arch-versatile/hardware.h +++ b/include/asm-arm/arch-versatile/hardware.h | |||
@@ -25,19 +25,26 @@ | |||
25 | #include <asm/sizes.h> | 25 | #include <asm/sizes.h> |
26 | #include <asm/arch/platform.h> | 26 | #include <asm/arch/platform.h> |
27 | 27 | ||
28 | // FIXME = PCI settings need to be fixed!!!!! | ||
29 | |||
30 | /* | 28 | /* |
31 | * Similar to above, but for PCI addresses (memory, IO, Config and the | 29 | * PCI space virtual addresses |
32 | * V3 chip itself). WARNING: this has to mirror definitions in platform.h | ||
33 | */ | 30 | */ |
34 | #define PCI_MEMORY_VADDR 0xe8000000 | 31 | #define VERSATILE_PCI_VIRT_BASE 0xe8000000 |
35 | #define PCI_CONFIG_VADDR 0xec000000 | 32 | #define VERSATILE_PCI_CFG_VIRT_BASE 0xe9000000 |
36 | #define PCI_V3_VADDR 0xed000000 | 33 | |
37 | #define PCI_IO_VADDR 0xee000000 | 34 | #if 0 |
35 | #define VERSATILE_PCI_VIRT_MEM_BASE0 0xf4000000 | ||
36 | #define VERSATILE_PCI_VIRT_MEM_BASE1 0xf5000000 | ||
37 | #define VERSATILE_PCI_VIRT_MEM_BASE2 0xf6000000 | ||
38 | |||
39 | #define PCIO_BASE VERSATILE_PCI_VIRT_MEM_BASE0 | ||
40 | #define PCIMEM_BASE VERSATILE_PCI_VIRT_MEM_BASE1 | ||
41 | #endif | ||
42 | |||
43 | /* CIK guesswork */ | ||
44 | #define PCIBIOS_MIN_IO 0x44000000 | ||
45 | #define PCIBIOS_MIN_MEM 0x50000000 | ||
38 | 46 | ||
39 | #define PCIO_BASE PCI_IO_VADDR | 47 | #define pcibios_assign_all_busses() 1 |
40 | #define PCIMEM_BASE PCI_MEMORY_VADDR | ||
41 | 48 | ||
42 | /* macro to get at IO space when running virtually */ | 49 | /* macro to get at IO space when running virtually */ |
43 | #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) | 50 | #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) |
diff --git a/include/asm-arm/arch-versatile/io.h b/include/asm-arm/arch-versatile/io.h index dbb7158788fc..9f895bf61494 100644 --- a/include/asm-arm/arch-versatile/io.h +++ b/include/asm-arm/arch-versatile/io.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #ifndef __ASM_ARM_ARCH_IO_H | 20 | #ifndef __ASM_ARM_ARCH_IO_H |
21 | #define __ASM_ARM_ARCH_IO_H | 21 | #define __ASM_ARM_ARCH_IO_H |
22 | 22 | ||
23 | #define IO_SPACE_LIMIT 0xffff | 23 | #define IO_SPACE_LIMIT 0xffffffff |
24 | 24 | ||
25 | #define __io(a) ((void __iomem *)(a)) | 25 | #define __io(a) ((void __iomem *)(a)) |
26 | #define __mem_pci(a) (a) | 26 | #define __mem_pci(a) (a) |
diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h index a71093e44c58..cbdd9fb96332 100644 --- a/include/asm-arm/arch-versatile/platform.h +++ b/include/asm-arm/arch-versatile/platform.h | |||
@@ -76,7 +76,7 @@ | |||
76 | #define VERSATILE_SYS_NVFLAGSSET_OFFSET 0x38 | 76 | #define VERSATILE_SYS_NVFLAGSSET_OFFSET 0x38 |
77 | #define VERSATILE_SYS_NVFLAGSCLR_OFFSET 0x3C | 77 | #define VERSATILE_SYS_NVFLAGSCLR_OFFSET 0x3C |
78 | #define VERSATILE_SYS_RESETCTL_OFFSET 0x40 | 78 | #define VERSATILE_SYS_RESETCTL_OFFSET 0x40 |
79 | #define VERSATILE_SYS_PICCTL_OFFSET 0x44 | 79 | #define VERSATILE_SYS_PCICTL_OFFSET 0x44 |
80 | #define VERSATILE_SYS_MCI_OFFSET 0x48 | 80 | #define VERSATILE_SYS_MCI_OFFSET 0x48 |
81 | #define VERSATILE_SYS_FLASH_OFFSET 0x4C | 81 | #define VERSATILE_SYS_FLASH_OFFSET 0x4C |
82 | #define VERSATILE_SYS_CLCD_OFFSET 0x50 | 82 | #define VERSATILE_SYS_CLCD_OFFSET 0x50 |
@@ -114,7 +114,7 @@ | |||
114 | #define VERSATILE_SYS_NVFLAGSSET (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET) | 114 | #define VERSATILE_SYS_NVFLAGSSET (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET) |
115 | #define VERSATILE_SYS_NVFLAGSCLR (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET) | 115 | #define VERSATILE_SYS_NVFLAGSCLR (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET) |
116 | #define VERSATILE_SYS_RESETCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET) | 116 | #define VERSATILE_SYS_RESETCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET) |
117 | #define VERSATILE_SYS_PICCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_PICCTL_OFFSET) | 117 | #define VERSATILE_SYS_PCICTL (VERSATILE_SYS_BASE + VERSATILE_SYS_PCICTL_OFFSET) |
118 | #define VERSATILE_SYS_MCI (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET) | 118 | #define VERSATILE_SYS_MCI (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET) |
119 | #define VERSATILE_SYS_FLASH (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET) | 119 | #define VERSATILE_SYS_FLASH (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET) |
120 | #define VERSATILE_SYS_CLCD (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET) | 120 | #define VERSATILE_SYS_CLCD (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET) |
@@ -225,7 +225,20 @@ | |||
225 | #define VERSATILE_SSMC_BASE 0x20000000 /* SSMC */ | 225 | #define VERSATILE_SSMC_BASE 0x20000000 /* SSMC */ |
226 | #define VERSATILE_IB2_BASE 0x24000000 /* IB2 module */ | 226 | #define VERSATILE_IB2_BASE 0x24000000 /* IB2 module */ |
227 | #define VERSATILE_MBX_BASE 0x40000000 /* MBX */ | 227 | #define VERSATILE_MBX_BASE 0x40000000 /* MBX */ |
228 | |||
229 | /* PCI space */ | ||
228 | #define VERSATILE_PCI_BASE 0x41000000 /* PCI Interface */ | 230 | #define VERSATILE_PCI_BASE 0x41000000 /* PCI Interface */ |
231 | #define VERSATILE_PCI_CFG_BASE 0x42000000 | ||
232 | #define VERSATILE_PCI_MEM_BASE0 0x44000000 | ||
233 | #define VERSATILE_PCI_MEM_BASE1 0x50000000 | ||
234 | #define VERSATILE_PCI_MEM_BASE2 0x60000000 | ||
235 | /* Sizes of above maps */ | ||
236 | #define VERSATILE_PCI_BASE_SIZE 0x01000000 | ||
237 | #define VERSATILE_PCI_CFG_BASE_SIZE 0x02000000 | ||
238 | #define VERSATILE_PCI_MEM_BASE0_SIZE 0x0c000000 /* 32Mb */ | ||
239 | #define VERSATILE_PCI_MEM_BASE1_SIZE 0x10000000 /* 256Mb */ | ||
240 | #define VERSATILE_PCI_MEM_BASE2_SIZE 0x10000000 /* 256Mb */ | ||
241 | |||
229 | #define VERSATILE_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */ | 242 | #define VERSATILE_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */ |
230 | #define VERSATILE_LT_BASE 0x80000000 /* Logic Tile expansion */ | 243 | #define VERSATILE_LT_BASE 0x80000000 /* Logic Tile expansion */ |
231 | 244 | ||
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 09ffeed507c2..035cdcff43d2 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h | |||
@@ -16,6 +16,9 @@ | |||
16 | 16 | ||
17 | #include <asm/mman.h> | 17 | #include <asm/mman.h> |
18 | #include <asm/glue.h> | 18 | #include <asm/glue.h> |
19 | #include <asm/shmparam.h> | ||
20 | |||
21 | #define CACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) | ||
19 | 22 | ||
20 | /* | 23 | /* |
21 | * Cache Model | 24 | * Cache Model |
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index 658ffa384fda..08a46302d265 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h | |||
@@ -273,6 +273,33 @@ extern void __iounmap(void __iomem *addr); | |||
273 | #endif | 273 | #endif |
274 | 274 | ||
275 | /* | 275 | /* |
276 | * io{read,write}{8,16,32} macros | ||
277 | */ | ||
278 | #define ioread8(p) ({ unsigned int __v = __raw_readb(p); __v; }) | ||
279 | #define ioread16(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; }) | ||
280 | #define ioread32(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; }) | ||
281 | |||
282 | #define iowrite8(v,p) __raw_writeb(v, p) | ||
283 | #define iowrite16(v,p) __raw_writew(cpu_to_le16(v), p) | ||
284 | #define iowrite32(v,p) __raw_writel(cpu_to_le32(v), p) | ||
285 | |||
286 | #define ioread8_rep(p,d,c) __raw_readsb(p,d,c) | ||
287 | #define ioread16_rep(p,d,c) __raw_readsw(p,d,c) | ||
288 | #define ioread32_rep(p,d,c) __raw_readsl(p,d,c) | ||
289 | |||
290 | #define iowrite8_rep(p,s,c) __raw_writesb(p,s,c) | ||
291 | #define iowrite16_rep(p,s,c) __raw_writesw(p,s,c) | ||
292 | #define iowrite32_rep(p,s,c) __raw_writesl(p,s,c) | ||
293 | |||
294 | extern void __iomem *ioport_map(unsigned long port, unsigned int nr); | ||
295 | extern void ioport_unmap(void __iomem *addr); | ||
296 | |||
297 | struct pci_dev; | ||
298 | |||
299 | extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen); | ||
300 | extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr); | ||
301 | |||
302 | /* | ||
276 | * can the hardware map this into one segment or not, given no other | 303 | * can the hardware map this into one segment or not, given no other |
277 | * constraints. | 304 | * constraints. |
278 | */ | 305 | */ |
diff --git a/include/linux/atalk.h b/include/linux/atalk.h index 31d3fc25ccbd..09a1451c1159 100644 --- a/include/linux/atalk.h +++ b/include/linux/atalk.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0) | 20 | #define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0) |
21 | 21 | ||
22 | struct atalk_addr { | 22 | struct atalk_addr { |
23 | __u16 s_net; | 23 | __be16 s_net; |
24 | __u8 s_node; | 24 | __u8 s_node; |
25 | }; | 25 | }; |
26 | 26 | ||
@@ -33,8 +33,8 @@ struct sockaddr_at { | |||
33 | 33 | ||
34 | struct atalk_netrange { | 34 | struct atalk_netrange { |
35 | __u8 nr_phase; | 35 | __u8 nr_phase; |
36 | __u16 nr_firstnet; | 36 | __be16 nr_firstnet; |
37 | __u16 nr_lastnet; | 37 | __be16 nr_lastnet; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #ifdef __KERNEL__ | 40 | #ifdef __KERNEL__ |
@@ -70,8 +70,8 @@ struct atalk_iface { | |||
70 | struct atalk_sock { | 70 | struct atalk_sock { |
71 | /* struct sock has to be the first member of atalk_sock */ | 71 | /* struct sock has to be the first member of atalk_sock */ |
72 | struct sock sk; | 72 | struct sock sk; |
73 | unsigned short dest_net; | 73 | __be16 dest_net; |
74 | unsigned short src_net; | 74 | __be16 src_net; |
75 | unsigned char dest_node; | 75 | unsigned char dest_node; |
76 | unsigned char src_node; | 76 | unsigned char src_node; |
77 | unsigned char dest_port; | 77 | unsigned char dest_port; |
@@ -95,9 +95,9 @@ struct ddpehdr { | |||
95 | deh_hops:4, | 95 | deh_hops:4, |
96 | deh_len:10; | 96 | deh_len:10; |
97 | #endif | 97 | #endif |
98 | __u16 deh_sum; | 98 | __be16 deh_sum; |
99 | __u16 deh_dnet; | 99 | __be16 deh_dnet; |
100 | __u16 deh_snet; | 100 | __be16 deh_snet; |
101 | __u8 deh_dnode; | 101 | __u8 deh_dnode; |
102 | __u8 deh_snode; | 102 | __u8 deh_snode; |
103 | __u8 deh_dport; | 103 | __u8 deh_dport; |
@@ -142,24 +142,24 @@ struct ddpshdr { | |||
142 | 142 | ||
143 | /* AppleTalk AARP headers */ | 143 | /* AppleTalk AARP headers */ |
144 | struct elapaarp { | 144 | struct elapaarp { |
145 | __u16 hw_type; | 145 | __be16 hw_type; |
146 | #define AARP_HW_TYPE_ETHERNET 1 | 146 | #define AARP_HW_TYPE_ETHERNET 1 |
147 | #define AARP_HW_TYPE_TOKENRING 2 | 147 | #define AARP_HW_TYPE_TOKENRING 2 |
148 | __u16 pa_type; | 148 | __be16 pa_type; |
149 | __u8 hw_len; | 149 | __u8 hw_len; |
150 | __u8 pa_len; | 150 | __u8 pa_len; |
151 | #define AARP_PA_ALEN 4 | 151 | #define AARP_PA_ALEN 4 |
152 | __u16 function; | 152 | __be16 function; |
153 | #define AARP_REQUEST 1 | 153 | #define AARP_REQUEST 1 |
154 | #define AARP_REPLY 2 | 154 | #define AARP_REPLY 2 |
155 | #define AARP_PROBE 3 | 155 | #define AARP_PROBE 3 |
156 | __u8 hw_src[ETH_ALEN] __attribute__ ((packed)); | 156 | __u8 hw_src[ETH_ALEN] __attribute__ ((packed)); |
157 | __u8 pa_src_zero __attribute__ ((packed)); | 157 | __u8 pa_src_zero __attribute__ ((packed)); |
158 | __u16 pa_src_net __attribute__ ((packed)); | 158 | __be16 pa_src_net __attribute__ ((packed)); |
159 | __u8 pa_src_node __attribute__ ((packed)); | 159 | __u8 pa_src_node __attribute__ ((packed)); |
160 | __u8 hw_dst[ETH_ALEN] __attribute__ ((packed)); | 160 | __u8 hw_dst[ETH_ALEN] __attribute__ ((packed)); |
161 | __u8 pa_dst_zero __attribute__ ((packed)); | 161 | __u8 pa_dst_zero __attribute__ ((packed)); |
162 | __u16 pa_dst_net __attribute__ ((packed)); | 162 | __be16 pa_dst_net __attribute__ ((packed)); |
163 | __u8 pa_dst_node __attribute__ ((packed)); | 163 | __u8 pa_dst_node __attribute__ ((packed)); |
164 | }; | 164 | }; |
165 | 165 | ||
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index e38407a23d04..561d4dc75836 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define NETLINK_SELINUX 7 /* SELinux event notifications */ | 14 | #define NETLINK_SELINUX 7 /* SELinux event notifications */ |
15 | #define NETLINK_ARPD 8 | 15 | #define NETLINK_ARPD 8 |
16 | #define NETLINK_AUDIT 9 /* auditing */ | 16 | #define NETLINK_AUDIT 9 /* auditing */ |
17 | #define NETLINK_FIB_LOOKUP 10 | ||
17 | #define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ | 18 | #define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ |
18 | #define NETLINK_IP6_FW 13 | 19 | #define NETLINK_IP6_FW 13 |
19 | #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ | 20 | #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ |
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index e6b519220245..724066778aff 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h | |||
@@ -245,6 +245,7 @@ struct sadb_x_nat_t_port { | |||
245 | 245 | ||
246 | /* Security Association flags */ | 246 | /* Security Association flags */ |
247 | #define SADB_SAFLAGS_PFS 1 | 247 | #define SADB_SAFLAGS_PFS 1 |
248 | #define SADB_SAFLAGS_NOPMTUDISC 0x20000000 | ||
248 | #define SADB_SAFLAGS_DECAP_DSCP 0x40000000 | 249 | #define SADB_SAFLAGS_DECAP_DSCP 0x40000000 |
249 | #define SADB_SAFLAGS_NOECN 0x80000000 | 250 | #define SADB_SAFLAGS_NOECN 0x80000000 |
250 | 251 | ||
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index d68391a9b9f3..f0d423300d84 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
@@ -196,6 +196,7 @@ struct xfrm_usersa_info { | |||
196 | __u8 flags; | 196 | __u8 flags; |
197 | #define XFRM_STATE_NOECN 1 | 197 | #define XFRM_STATE_NOECN 1 |
198 | #define XFRM_STATE_DECAP_DSCP 2 | 198 | #define XFRM_STATE_DECAP_DSCP 2 |
199 | #define XFRM_STATE_NOPMTUDISC 4 | ||
199 | }; | 200 | }; |
200 | 201 | ||
201 | struct xfrm_usersa_id { | 202 | struct xfrm_usersa_id { |
diff --git a/include/net/ax25.h b/include/net/ax25.h index 9e6368a54547..828a3a93dda1 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h | |||
@@ -220,7 +220,7 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25) | |||
220 | } | 220 | } |
221 | } | 221 | } |
222 | 222 | ||
223 | static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev) | 223 | static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev) |
224 | { | 224 | { |
225 | skb->dev = dev; | 225 | skb->dev = dev; |
226 | skb->pkt_type = PACKET_HOST; | 226 | skb->pkt_type = PACKET_HOST; |
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e5a5f6b62f88..a4208a336ac0 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -109,6 +109,20 @@ struct fib_result { | |||
109 | #endif | 109 | #endif |
110 | }; | 110 | }; |
111 | 111 | ||
112 | struct fib_result_nl { | ||
113 | u32 fl_addr; /* To be looked up*/ | ||
114 | u32 fl_fwmark; | ||
115 | unsigned char fl_tos; | ||
116 | unsigned char fl_scope; | ||
117 | unsigned char tb_id_in; | ||
118 | |||
119 | unsigned char tb_id; /* Results */ | ||
120 | unsigned char prefixlen; | ||
121 | unsigned char nh_sel; | ||
122 | unsigned char type; | ||
123 | unsigned char scope; | ||
124 | int err; | ||
125 | }; | ||
112 | 126 | ||
113 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 127 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
114 | 128 | ||
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index ebc5282e6d58..dc107ffad483 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h | |||
@@ -65,9 +65,11 @@ typedef enum { | |||
65 | SCTP_CMD_TIMER_START, /* Start a timer. */ | 65 | SCTP_CMD_TIMER_START, /* Start a timer. */ |
66 | SCTP_CMD_TIMER_RESTART, /* Restart a timer. */ | 66 | SCTP_CMD_TIMER_RESTART, /* Restart a timer. */ |
67 | SCTP_CMD_TIMER_STOP, /* Stop a timer. */ | 67 | SCTP_CMD_TIMER_STOP, /* Stop a timer. */ |
68 | SCTP_CMD_COUNTER_RESET, /* Reset a counter. */ | 68 | SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */ |
69 | SCTP_CMD_COUNTER_INC, /* Increment a counter. */ | 69 | SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */ |
70 | SCTP_CMD_INIT_COUNTER_INC, /* Increment init counter. */ | ||
70 | SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */ | 71 | SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */ |
72 | SCTP_CMD_COOKIEECHO_RESTART, /* High level, do cookie-echo timer work. */ | ||
71 | SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ | 73 | SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ |
72 | SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ | 74 | SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ |
73 | SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ | 75 | SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ |
@@ -118,7 +120,6 @@ typedef union { | |||
118 | int error; | 120 | int error; |
119 | sctp_state_t state; | 121 | sctp_state_t state; |
120 | sctp_event_timeout_t to; | 122 | sctp_event_timeout_t to; |
121 | sctp_counter_t counter; | ||
122 | void *ptr; | 123 | void *ptr; |
123 | struct sctp_chunk *chunk; | 124 | struct sctp_chunk *chunk; |
124 | struct sctp_association *asoc; | 125 | struct sctp_association *asoc; |
@@ -165,7 +166,6 @@ SCTP_ARG_CONSTRUCTOR(U16, __u16, u16) | |||
165 | SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) | 166 | SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) |
166 | SCTP_ARG_CONSTRUCTOR(ERROR, int, error) | 167 | SCTP_ARG_CONSTRUCTOR(ERROR, int, error) |
167 | SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) | 168 | SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) |
168 | SCTP_ARG_CONSTRUCTOR(COUNTER, sctp_counter_t, counter) | ||
169 | SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) | 169 | SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) |
170 | SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) | 170 | SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) |
171 | SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk) | 171 | SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk) |
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 2b76c0f4babc..4868c7f7749d 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h | |||
@@ -263,13 +263,6 @@ enum { SCTP_MIN_PMTU = 576 }; | |||
263 | enum { SCTP_MAX_DUP_TSNS = 16 }; | 263 | enum { SCTP_MAX_DUP_TSNS = 16 }; |
264 | enum { SCTP_MAX_GABS = 16 }; | 264 | enum { SCTP_MAX_GABS = 16 }; |
265 | 265 | ||
266 | typedef enum { | ||
267 | SCTP_COUNTER_INIT_ERROR, | ||
268 | } sctp_counter_t; | ||
269 | |||
270 | /* How many counters does an association need? */ | ||
271 | #define SCTP_NUMBER_COUNTERS 5 | ||
272 | |||
273 | /* Here we define the default timers. */ | 266 | /* Here we define the default timers. */ |
274 | 267 | ||
275 | /* cookie timer def = ? seconds */ | 268 | /* cookie timer def = ? seconds */ |
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 960abfa48d68..ef2738159ab3 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -223,6 +223,22 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics); | |||
223 | extern int sctp_debug_flag; | 223 | extern int sctp_debug_flag; |
224 | #define SCTP_DEBUG_PRINTK(whatever...) \ | 224 | #define SCTP_DEBUG_PRINTK(whatever...) \ |
225 | ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) | 225 | ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) |
226 | #define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \ | ||
227 | if (sctp_debug_flag) { \ | ||
228 | if (saddr->sa.sa_family == AF_INET6) { \ | ||
229 | printk(KERN_DEBUG \ | ||
230 | lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \ | ||
231 | leadparm, \ | ||
232 | NIP6(saddr->v6.sin6_addr), \ | ||
233 | otherparms); \ | ||
234 | } else { \ | ||
235 | printk(KERN_DEBUG \ | ||
236 | lead "%u.%u.%u.%u" trail, \ | ||
237 | leadparm, \ | ||
238 | NIPQUAD(saddr->v4.sin_addr.s_addr), \ | ||
239 | otherparms); \ | ||
240 | } \ | ||
241 | } | ||
226 | #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } | 242 | #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } |
227 | #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } | 243 | #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } |
228 | 244 | ||
@@ -236,6 +252,7 @@ extern int sctp_debug_flag; | |||
236 | #else /* SCTP_DEBUG */ | 252 | #else /* SCTP_DEBUG */ |
237 | 253 | ||
238 | #define SCTP_DEBUG_PRINTK(whatever...) | 254 | #define SCTP_DEBUG_PRINTK(whatever...) |
255 | #define SCTP_DEBUG_PRINTK_IPADDR(whatever...) | ||
239 | #define SCTP_ENABLE_DEBUG | 256 | #define SCTP_ENABLE_DEBUG |
240 | #define SCTP_DISABLE_DEBUG | 257 | #define SCTP_DISABLE_DEBUG |
241 | #define SCTP_ASSERT(expr, str, func) | 258 | #define SCTP_ASSERT(expr, str, func) |
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index f4fcee104707..a53e08a45e32 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h | |||
@@ -116,7 +116,8 @@ sctp_state_fn_t sctp_sf_eat_data_fast_4_4; | |||
116 | sctp_state_fn_t sctp_sf_eat_sack_6_2; | 116 | sctp_state_fn_t sctp_sf_eat_sack_6_2; |
117 | sctp_state_fn_t sctp_sf_tabort_8_4_8; | 117 | sctp_state_fn_t sctp_sf_tabort_8_4_8; |
118 | sctp_state_fn_t sctp_sf_operr_notify; | 118 | sctp_state_fn_t sctp_sf_operr_notify; |
119 | sctp_state_fn_t sctp_sf_t1_timer_expire; | 119 | sctp_state_fn_t sctp_sf_t1_init_timer_expire; |
120 | sctp_state_fn_t sctp_sf_t1_cookie_timer_expire; | ||
120 | sctp_state_fn_t sctp_sf_t2_timer_expire; | 121 | sctp_state_fn_t sctp_sf_t2_timer_expire; |
121 | sctp_state_fn_t sctp_sf_t4_timer_expire; | 122 | sctp_state_fn_t sctp_sf_t4_timer_expire; |
122 | sctp_state_fn_t sctp_sf_t5_timer_expire; | 123 | sctp_state_fn_t sctp_sf_t5_timer_expire; |
@@ -258,7 +259,10 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, | |||
258 | void sctp_chunk_assign_tsn(struct sctp_chunk *); | 259 | void sctp_chunk_assign_tsn(struct sctp_chunk *); |
259 | void sctp_chunk_assign_ssn(struct sctp_chunk *); | 260 | void sctp_chunk_assign_ssn(struct sctp_chunk *); |
260 | 261 | ||
261 | void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error); | 262 | sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
263 | __u16 error, | ||
264 | const struct sctp_association *asoc, | ||
265 | struct sctp_transport *transport); | ||
262 | 266 | ||
263 | /* Prototypes for statetable processing. */ | 267 | /* Prototypes for statetable processing. */ |
264 | 268 | ||
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 6c24d9cd3d66..dfad4d3c581c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -867,10 +867,13 @@ struct sctp_transport { | |||
867 | */ | 867 | */ |
868 | unsigned long last_time_ecne_reduced; | 868 | unsigned long last_time_ecne_reduced; |
869 | 869 | ||
870 | /* active : The current active state of this destination, | 870 | /* The number of times INIT has been sent on this transport. */ |
871 | * : i.e. DOWN, UP, etc. | 871 | int init_sent_count; |
872 | |||
873 | /* state : The current state of this destination, | ||
874 | * : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN. | ||
872 | */ | 875 | */ |
873 | int active; | 876 | int state; |
874 | 877 | ||
875 | /* hb_allowed : The current heartbeat state of this destination, | 878 | /* hb_allowed : The current heartbeat state of this destination, |
876 | * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. | 879 | * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. |
@@ -1222,9 +1225,6 @@ struct sctp_endpoint { | |||
1222 | 1225 | ||
1223 | /* sendbuf acct. policy. */ | 1226 | /* sendbuf acct. policy. */ |
1224 | __u32 sndbuf_policy; | 1227 | __u32 sndbuf_policy; |
1225 | |||
1226 | /* Name for debugging output... */ | ||
1227 | char *debug_name; | ||
1228 | }; | 1228 | }; |
1229 | 1229 | ||
1230 | /* Recover the outter endpoint structure. */ | 1230 | /* Recover the outter endpoint structure. */ |
@@ -1314,11 +1314,23 @@ struct sctp_association { | |||
1314 | * : association. Normally this information is | 1314 | * : association. Normally this information is |
1315 | * : hashed or keyed for quick lookup and access | 1315 | * : hashed or keyed for quick lookup and access |
1316 | * : of the TCB. | 1316 | * : of the TCB. |
1317 | * : The list is also initialized with the list | ||
1318 | * : of addresses passed with the sctp_connectx() | ||
1319 | * : call. | ||
1317 | * | 1320 | * |
1318 | * It is a list of SCTP_transport's. | 1321 | * It is a list of SCTP_transport's. |
1319 | */ | 1322 | */ |
1320 | struct list_head transport_addr_list; | 1323 | struct list_head transport_addr_list; |
1321 | 1324 | ||
1325 | /* transport_count | ||
1326 | * | ||
1327 | * Peer : A count of the number of peer addresses | ||
1328 | * Transport : in the Peer Transport Address List. | ||
1329 | * Address : | ||
1330 | * Count : | ||
1331 | */ | ||
1332 | __u16 transport_count; | ||
1333 | |||
1322 | /* port | 1334 | /* port |
1323 | * The transport layer port number. | 1335 | * The transport layer port number. |
1324 | */ | 1336 | */ |
@@ -1486,6 +1498,9 @@ struct sctp_association { | |||
1486 | /* Transport to which SHUTDOWN chunk was last sent. */ | 1498 | /* Transport to which SHUTDOWN chunk was last sent. */ |
1487 | struct sctp_transport *shutdown_last_sent_to; | 1499 | struct sctp_transport *shutdown_last_sent_to; |
1488 | 1500 | ||
1501 | /* Transport to which INIT chunk was last sent. */ | ||
1502 | struct sctp_transport *init_last_sent_to; | ||
1503 | |||
1489 | /* Next TSN : The next TSN number to be assigned to a new | 1504 | /* Next TSN : The next TSN number to be assigned to a new |
1490 | * : DATA chunk. This is sent in the INIT or INIT | 1505 | * : DATA chunk. This is sent in the INIT or INIT |
1491 | * : ACK chunk to the peer and incremented each | 1506 | * : ACK chunk to the peer and incremented each |
@@ -1549,8 +1564,11 @@ struct sctp_association { | |||
1549 | /* The message size at which SCTP fragmentation will occur. */ | 1564 | /* The message size at which SCTP fragmentation will occur. */ |
1550 | __u32 frag_point; | 1565 | __u32 frag_point; |
1551 | 1566 | ||
1552 | /* Currently only one counter is used to count INIT errors. */ | 1567 | /* Counter used to count INIT errors. */ |
1553 | int counters[SCTP_NUMBER_COUNTERS]; | 1568 | int init_err_counter; |
1569 | |||
1570 | /* Count the number of INIT cycles (for doubling timeout). */ | ||
1571 | int init_cycle; | ||
1554 | 1572 | ||
1555 | /* Default send parameters. */ | 1573 | /* Default send parameters. */ |
1556 | __u16 default_stream; | 1574 | __u16 default_stream; |
@@ -1708,6 +1726,8 @@ void sctp_association_free(struct sctp_association *); | |||
1708 | void sctp_association_put(struct sctp_association *); | 1726 | void sctp_association_put(struct sctp_association *); |
1709 | void sctp_association_hold(struct sctp_association *); | 1727 | void sctp_association_hold(struct sctp_association *); |
1710 | 1728 | ||
1729 | struct sctp_transport *sctp_assoc_choose_init_transport( | ||
1730 | struct sctp_association *); | ||
1711 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( | 1731 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( |
1712 | struct sctp_association *); | 1732 | struct sctp_association *); |
1713 | void sctp_assoc_update_retran_path(struct sctp_association *); | 1733 | void sctp_assoc_update_retran_path(struct sctp_association *); |
@@ -1717,9 +1737,12 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc, | |||
1717 | const union sctp_addr *laddr); | 1737 | const union sctp_addr *laddr); |
1718 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, | 1738 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, |
1719 | const union sctp_addr *address, | 1739 | const union sctp_addr *address, |
1720 | const int gfp); | 1740 | const int gfp, |
1741 | const int peer_state); | ||
1721 | void sctp_assoc_del_peer(struct sctp_association *asoc, | 1742 | void sctp_assoc_del_peer(struct sctp_association *asoc, |
1722 | const union sctp_addr *addr); | 1743 | const union sctp_addr *addr); |
1744 | void sctp_assoc_rm_peer(struct sctp_association *asoc, | ||
1745 | struct sctp_transport *peer); | ||
1723 | void sctp_assoc_control_transport(struct sctp_association *, | 1746 | void sctp_assoc_control_transport(struct sctp_association *, |
1724 | struct sctp_transport *, | 1747 | struct sctp_transport *, |
1725 | sctp_transport_cmd_t, sctp_sn_error_t); | 1748 | sctp_transport_cmd_t, sctp_sn_error_t); |
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 2758e8ce4f25..f6328aeddcce 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
@@ -111,6 +111,8 @@ enum sctp_optname { | |||
111 | #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM | 111 | #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM |
112 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ | 112 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ |
113 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS | 113 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS |
114 | SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ | ||
115 | #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX | ||
114 | }; | 116 | }; |
115 | 117 | ||
116 | /* | 118 | /* |
@@ -527,6 +529,7 @@ struct sctp_paddrinfo { | |||
527 | enum sctp_spinfo_state { | 529 | enum sctp_spinfo_state { |
528 | SCTP_INACTIVE, | 530 | SCTP_INACTIVE, |
529 | SCTP_ACTIVE, | 531 | SCTP_ACTIVE, |
532 | SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */ | ||
530 | }; | 533 | }; |
531 | 534 | ||
532 | /* | 535 | /* |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0e65e02b7a1d..029522a4ceda 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -204,6 +204,7 @@ struct xfrm_state_afinfo { | |||
204 | rwlock_t lock; | 204 | rwlock_t lock; |
205 | struct list_head *state_bydst; | 205 | struct list_head *state_bydst; |
206 | struct list_head *state_byspi; | 206 | struct list_head *state_byspi; |
207 | int (*init_flags)(struct xfrm_state *x); | ||
207 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, | 208 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, |
208 | struct xfrm_tmpl *tmpl, | 209 | struct xfrm_tmpl *tmpl, |
209 | xfrm_address_t *daddr, xfrm_address_t *saddr); | 210 | xfrm_address_t *daddr, xfrm_address_t *saddr); |
@@ -225,7 +226,7 @@ struct xfrm_type | |||
225 | struct module *owner; | 226 | struct module *owner; |
226 | __u8 proto; | 227 | __u8 proto; |
227 | 228 | ||
228 | int (*init_state)(struct xfrm_state *x, void *args); | 229 | int (*init_state)(struct xfrm_state *x); |
229 | void (*destructor)(struct xfrm_state *); | 230 | void (*destructor)(struct xfrm_state *); |
230 | int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); | 231 | int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); |
231 | int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); | 232 | 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); | |||
839 | extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); | 840 | extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); |
840 | extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); | 841 | extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); |
841 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); | 842 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); |
843 | extern int xfrm_init_state(struct xfrm_state *x); | ||
842 | extern int xfrm4_rcv(struct sk_buff *skb); | 844 | extern int xfrm4_rcv(struct sk_buff *skb); |
843 | extern int xfrm4_output(struct sk_buff *skb); | 845 | extern int xfrm4_output(struct sk_buff *skb); |
844 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); | 846 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); |
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 54640c01b50c..10d040461021 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c | |||
@@ -565,7 +565,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb, | |||
565 | * numbers we just happen to need. Now put the | 565 | * numbers we just happen to need. Now put the |
566 | * length in the lower two. | 566 | * length in the lower two. |
567 | */ | 567 | */ |
568 | *((__u16 *)skb->data) = htons(skb->len); | 568 | *((__be16 *)skb->data) = htons(skb->len); |
569 | ft = 1; | 569 | ft = 1; |
570 | } | 570 | } |
571 | /* | 571 | /* |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 876dbac71060..192b529f86a4 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -401,7 +401,7 @@ out_err: | |||
401 | } | 401 | } |
402 | 402 | ||
403 | /* Find a match for a specific network:node pair */ | 403 | /* Find a match for a specific network:node pair */ |
404 | static struct atalk_iface *atalk_find_interface(int net, int node) | 404 | static struct atalk_iface *atalk_find_interface(__be16 net, int node) |
405 | { | 405 | { |
406 | struct atalk_iface *iface; | 406 | struct atalk_iface *iface; |
407 | 407 | ||
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 0e98f2235b6e..514c85b2631a 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -200,7 +200,7 @@ static void ah4_err(struct sk_buff *skb, u32 info) | |||
200 | xfrm_state_put(x); | 200 | xfrm_state_put(x); |
201 | } | 201 | } |
202 | 202 | ||
203 | static int ah_init_state(struct xfrm_state *x, void *args) | 203 | static int ah_init_state(struct xfrm_state *x) |
204 | { | 204 | { |
205 | struct ah_data *ahp = NULL; | 205 | struct ah_data *ahp = NULL; |
206 | struct xfrm_algo_desc *aalg_desc; | 206 | struct xfrm_algo_desc *aalg_desc; |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index eae84cc39d3f..ba57446d5d1f 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -362,7 +362,7 @@ static void esp_destroy(struct xfrm_state *x) | |||
362 | kfree(esp); | 362 | kfree(esp); |
363 | } | 363 | } |
364 | 364 | ||
365 | static int esp_init_state(struct xfrm_state *x, void *args) | 365 | static int esp_init_state(struct xfrm_state *x) |
366 | { | 366 | { |
367 | struct esp_data *esp = NULL; | 367 | struct esp_data *esp = NULL; |
368 | 368 | ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 563e7d612706..cd8e45ab9580 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -516,6 +516,60 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
516 | #undef BRD1_OK | 516 | #undef BRD1_OK |
517 | } | 517 | } |
518 | 518 | ||
519 | static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | ||
520 | { | ||
521 | |||
522 | struct fib_result res; | ||
523 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, | ||
524 | .fwmark = frn->fl_fwmark, | ||
525 | .tos = frn->fl_tos, | ||
526 | .scope = frn->fl_scope } } }; | ||
527 | if (tb) { | ||
528 | local_bh_disable(); | ||
529 | |||
530 | frn->tb_id = tb->tb_id; | ||
531 | frn->err = tb->tb_lookup(tb, &fl, &res); | ||
532 | |||
533 | if (!frn->err) { | ||
534 | frn->prefixlen = res.prefixlen; | ||
535 | frn->nh_sel = res.nh_sel; | ||
536 | frn->type = res.type; | ||
537 | frn->scope = res.scope; | ||
538 | } | ||
539 | local_bh_enable(); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | static void nl_fib_input(struct sock *sk, int len) | ||
544 | { | ||
545 | struct sk_buff *skb = NULL; | ||
546 | struct nlmsghdr *nlh = NULL; | ||
547 | struct fib_result_nl *frn; | ||
548 | int err; | ||
549 | u32 pid; | ||
550 | struct fib_table *tb; | ||
551 | |||
552 | skb = skb_recv_datagram(sk, 0, 0, &err); | ||
553 | nlh = (struct nlmsghdr *)skb->data; | ||
554 | |||
555 | frn = (struct fib_result_nl *) NLMSG_DATA(nlh); | ||
556 | tb = fib_get_table(frn->tb_id_in); | ||
557 | |||
558 | nl_fib_lookup(frn, tb); | ||
559 | |||
560 | pid = nlh->nlmsg_pid; /*pid of sending process */ | ||
561 | NETLINK_CB(skb).groups = 0; /* not in mcast group */ | ||
562 | NETLINK_CB(skb).pid = 0; /* from kernel */ | ||
563 | NETLINK_CB(skb).dst_pid = pid; | ||
564 | NETLINK_CB(skb).dst_groups = 0; /* unicast */ | ||
565 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); | ||
566 | } | ||
567 | |||
568 | static void nl_fib_lookup_init(void) | ||
569 | { | ||
570 | netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input); | ||
571 | } | ||
572 | |||
519 | static void fib_disable_ip(struct net_device *dev, int force) | 573 | static void fib_disable_ip(struct net_device *dev, int force) |
520 | { | 574 | { |
521 | if (fib_sync_down(0, dev, force)) | 575 | if (fib_sync_down(0, dev, force)) |
@@ -604,6 +658,7 @@ void __init ip_fib_init(void) | |||
604 | 658 | ||
605 | register_netdevice_notifier(&fib_netdev_notifier); | 659 | register_netdevice_notifier(&fib_netdev_notifier); |
606 | register_inetaddr_notifier(&fib_inetaddr_notifier); | 660 | register_inetaddr_notifier(&fib_inetaddr_notifier); |
661 | nl_fib_lookup_init(); | ||
607 | } | 662 | } |
608 | 663 | ||
609 | EXPORT_SYMBOL(inet_addr_type); | 664 | EXPORT_SYMBOL(inet_addr_type); |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 1a23c5263b99..2065944fd9e5 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -236,15 +236,10 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) | |||
236 | t->props.mode = 1; | 236 | t->props.mode = 1; |
237 | t->props.saddr.a4 = x->props.saddr.a4; | 237 | t->props.saddr.a4 = x->props.saddr.a4; |
238 | t->props.flags = x->props.flags; | 238 | t->props.flags = x->props.flags; |
239 | 239 | ||
240 | t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family); | 240 | if (xfrm_init_state(t)) |
241 | if (t->type == NULL) | ||
242 | goto error; | ||
243 | |||
244 | if (t->type->init_state(t, NULL)) | ||
245 | goto error; | 241 | goto error; |
246 | 242 | ||
247 | t->km.state = XFRM_STATE_VALID; | ||
248 | atomic_set(&t->tunnel_users, 1); | 243 | atomic_set(&t->tunnel_users, 1); |
249 | out: | 244 | out: |
250 | return t; | 245 | return t; |
@@ -422,7 +417,7 @@ static void ipcomp_destroy(struct xfrm_state *x) | |||
422 | kfree(ipcd); | 417 | kfree(ipcd); |
423 | } | 418 | } |
424 | 419 | ||
425 | static int ipcomp_init_state(struct xfrm_state *x, void *args) | 420 | static int ipcomp_init_state(struct xfrm_state *x) |
426 | { | 421 | { |
427 | int err; | 422 | int err; |
428 | struct ipcomp_data *ipcd; | 423 | struct ipcomp_data *ipcd; |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index af2392ae5769..66620a95942a 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -33,6 +33,7 @@ static void xfrm4_encap(struct sk_buff *skb) | |||
33 | struct dst_entry *dst = skb->dst; | 33 | struct dst_entry *dst = skb->dst; |
34 | struct xfrm_state *x = dst->xfrm; | 34 | struct xfrm_state *x = dst->xfrm; |
35 | struct iphdr *iph, *top_iph; | 35 | struct iphdr *iph, *top_iph; |
36 | int flags; | ||
36 | 37 | ||
37 | iph = skb->nh.iph; | 38 | iph = skb->nh.iph; |
38 | skb->h.ipiph = iph; | 39 | skb->h.ipiph = iph; |
@@ -51,10 +52,13 @@ static void xfrm4_encap(struct sk_buff *skb) | |||
51 | 52 | ||
52 | /* DS disclosed */ | 53 | /* DS disclosed */ |
53 | top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos); | 54 | top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos); |
54 | if (x->props.flags & XFRM_STATE_NOECN) | 55 | |
56 | flags = x->props.flags; | ||
57 | if (flags & XFRM_STATE_NOECN) | ||
55 | IP_ECN_clear(top_iph); | 58 | IP_ECN_clear(top_iph); |
56 | 59 | ||
57 | top_iph->frag_off = iph->frag_off & htons(IP_DF); | 60 | top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? |
61 | 0 : (iph->frag_off & htons(IP_DF)); | ||
58 | if (!top_iph->frag_off) | 62 | if (!top_iph->frag_off) |
59 | __ip_select_ident(top_iph, dst, 0); | 63 | __ip_select_ident(top_iph, dst, 0); |
60 | 64 | ||
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 223a2e83853f..050611d7a967 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -7,12 +7,20 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <net/ip.h> | ||
10 | #include <net/xfrm.h> | 11 | #include <net/xfrm.h> |
11 | #include <linux/pfkeyv2.h> | 12 | #include <linux/pfkeyv2.h> |
12 | #include <linux/ipsec.h> | 13 | #include <linux/ipsec.h> |
13 | 14 | ||
14 | static struct xfrm_state_afinfo xfrm4_state_afinfo; | 15 | static struct xfrm_state_afinfo xfrm4_state_afinfo; |
15 | 16 | ||
17 | static int xfrm4_init_flags(struct xfrm_state *x) | ||
18 | { | ||
19 | if (ipv4_config.no_pmtu_disc) | ||
20 | x->props.flags |= XFRM_STATE_NOPMTUDISC; | ||
21 | return 0; | ||
22 | } | ||
23 | |||
16 | static void | 24 | static void |
17 | __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | 25 | __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, |
18 | struct xfrm_tmpl *tmpl, | 26 | struct xfrm_tmpl *tmpl, |
@@ -109,6 +117,7 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, | |||
109 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 117 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
110 | .family = AF_INET, | 118 | .family = AF_INET, |
111 | .lock = RW_LOCK_UNLOCKED, | 119 | .lock = RW_LOCK_UNLOCKED, |
120 | .init_flags = xfrm4_init_flags, | ||
112 | .init_tempsel = __xfrm4_init_tempsel, | 121 | .init_tempsel = __xfrm4_init_tempsel, |
113 | .state_lookup = __xfrm4_state_lookup, | 122 | .state_lookup = __xfrm4_state_lookup, |
114 | .find_acq = __xfrm4_find_acq, | 123 | .find_acq = __xfrm4_find_acq, |
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 413191f585f6..e1fe360ed27a 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
@@ -84,7 +84,7 @@ static void ipip_err(struct sk_buff *skb, u32 info) | |||
84 | handler->err_handler(skb, &arg); | 84 | handler->err_handler(skb, &arg); |
85 | } | 85 | } |
86 | 86 | ||
87 | static int ipip_init_state(struct xfrm_state *x, void *args) | 87 | static int ipip_init_state(struct xfrm_state *x) |
88 | { | 88 | { |
89 | if (!x->props.mode) | 89 | if (!x->props.mode) |
90 | return -EINVAL; | 90 | return -EINVAL; |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index e3ecf626cbf7..986fdfdccbcd 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -339,7 +339,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
339 | xfrm_state_put(x); | 339 | xfrm_state_put(x); |
340 | } | 340 | } |
341 | 341 | ||
342 | static int ah6_init_state(struct xfrm_state *x, void *args) | 342 | static int ah6_init_state(struct xfrm_state *x) |
343 | { | 343 | { |
344 | struct ah_data *ahp = NULL; | 344 | struct ah_data *ahp = NULL; |
345 | struct xfrm_algo_desc *aalg_desc; | 345 | struct xfrm_algo_desc *aalg_desc; |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index be7095d6babe..324db62515a2 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -296,7 +296,7 @@ static void esp6_destroy(struct xfrm_state *x) | |||
296 | kfree(esp); | 296 | kfree(esp); |
297 | } | 297 | } |
298 | 298 | ||
299 | static int esp6_init_state(struct xfrm_state *x, void *args) | 299 | static int esp6_init_state(struct xfrm_state *x) |
300 | { | 300 | { |
301 | struct esp_data *esp = NULL; | 301 | struct esp_data *esp = NULL; |
302 | 302 | ||
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 6cde5310cd76..423feb46ccc0 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -234,14 +234,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | |||
234 | t->props.mode = 1; | 234 | t->props.mode = 1; |
235 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); | 235 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); |
236 | 236 | ||
237 | t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family); | 237 | if (xfrm_init_state(t)) |
238 | if (t->type == NULL) | ||
239 | goto error; | 238 | goto error; |
240 | 239 | ||
241 | if (t->type->init_state(t, NULL)) | ||
242 | goto error; | ||
243 | |||
244 | t->km.state = XFRM_STATE_VALID; | ||
245 | atomic_set(&t->tunnel_users, 1); | 240 | atomic_set(&t->tunnel_users, 1); |
246 | 241 | ||
247 | out: | 242 | out: |
@@ -420,7 +415,7 @@ static void ipcomp6_destroy(struct xfrm_state *x) | |||
420 | xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); | 415 | xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); |
421 | } | 416 | } |
422 | 417 | ||
423 | static int ipcomp6_init_state(struct xfrm_state *x, void *args) | 418 | static int ipcomp6_init_state(struct xfrm_state *x) |
424 | { | 419 | { |
425 | int err; | 420 | int err; |
426 | struct ipcomp_data *ipcd; | 421 | struct ipcomp_data *ipcd; |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index ffcadd68b951..60c26c87277e 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -466,7 +466,7 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
466 | return; | 466 | return; |
467 | } | 467 | } |
468 | 468 | ||
469 | static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args) | 469 | static int xfrm6_tunnel_init_state(struct xfrm_state *x) |
470 | { | 470 | { |
471 | if (!x->props.mode) | 471 | if (!x->props.mode) |
472 | return -EINVAL; | 472 | return -EINVAL; |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 98b72f2024ff..4879743b945a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -690,6 +690,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
690 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; | 690 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; |
691 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) | 691 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
692 | sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; | 692 | sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; |
693 | if (x->props.flags & XFRM_STATE_NOPMTUDISC) | ||
694 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC; | ||
693 | 695 | ||
694 | /* hard time */ | 696 | /* hard time */ |
695 | if (hsc & 2) { | 697 | if (hsc & 2) { |
@@ -974,6 +976,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
974 | x->props.flags |= XFRM_STATE_NOECN; | 976 | x->props.flags |= XFRM_STATE_NOECN; |
975 | if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP) | 977 | if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP) |
976 | x->props.flags |= XFRM_STATE_DECAP_DSCP; | 978 | x->props.flags |= XFRM_STATE_DECAP_DSCP; |
979 | if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC) | ||
980 | x->props.flags |= XFRM_STATE_NOPMTUDISC; | ||
977 | 981 | ||
978 | lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; | 982 | lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; |
979 | if (lifetime != NULL) { | 983 | if (lifetime != NULL) { |
@@ -1096,17 +1100,11 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
1096 | } | 1100 | } |
1097 | } | 1101 | } |
1098 | 1102 | ||
1099 | x->type = xfrm_get_type(proto, x->props.family); | 1103 | err = xfrm_init_state(x); |
1100 | if (x->type == NULL) { | 1104 | if (err) |
1101 | err = -ENOPROTOOPT; | ||
1102 | goto out; | ||
1103 | } | ||
1104 | if (x->type->init_state(x, NULL)) { | ||
1105 | err = -EINVAL; | ||
1106 | goto out; | 1105 | goto out; |
1107 | } | 1106 | |
1108 | x->km.seq = hdr->sadb_msg_seq; | 1107 | x->km.seq = hdr->sadb_msg_seq; |
1109 | x->km.state = XFRM_STATE_VALID; | ||
1110 | return x; | 1108 | return x; |
1111 | 1109 | ||
1112 | out: | 1110 | out: |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 663843d97a92..7ae6aa772dab 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -191,10 +191,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; | 191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; |
192 | asoc->unack_data = 0; | 192 | asoc->unack_data = 0; |
193 | 193 | ||
194 | SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n", | ||
195 | asoc->ep->debug_name, | ||
196 | asoc->ctsn_ack_point); | ||
197 | |||
198 | /* ADDIP Section 4.1 Asconf Chunk Procedures | 194 | /* ADDIP Section 4.1 Asconf Chunk Procedures |
199 | * | 195 | * |
200 | * When an endpoint has an ASCONF signaled change to be sent to the | 196 | * 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 | |||
211 | 207 | ||
212 | /* Make an empty list of remote transport addresses. */ | 208 | /* Make an empty list of remote transport addresses. */ |
213 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); | 209 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); |
210 | asoc->peer.transport_count = 0; | ||
214 | 211 | ||
215 | /* RFC 2960 5.1 Normal Establishment of an Association | 212 | /* RFC 2960 5.1 Normal Establishment of an Association |
216 | * | 213 | * |
@@ -288,6 +285,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep, | |||
288 | 285 | ||
289 | asoc->base.malloced = 1; | 286 | asoc->base.malloced = 1; |
290 | SCTP_DBG_OBJCNT_INC(assoc); | 287 | SCTP_DBG_OBJCNT_INC(assoc); |
288 | SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc); | ||
291 | 289 | ||
292 | return asoc; | 290 | return asoc; |
293 | 291 | ||
@@ -356,6 +354,8 @@ void sctp_association_free(struct sctp_association *asoc) | |||
356 | sctp_transport_free(transport); | 354 | sctp_transport_free(transport); |
357 | } | 355 | } |
358 | 356 | ||
357 | asoc->peer.transport_count = 0; | ||
358 | |||
359 | /* Free any cached ASCONF_ACK chunk. */ | 359 | /* Free any cached ASCONF_ACK chunk. */ |
360 | if (asoc->addip_last_asconf_ack) | 360 | if (asoc->addip_last_asconf_ack) |
361 | sctp_chunk_free(asoc->addip_last_asconf_ack); | 361 | sctp_chunk_free(asoc->addip_last_asconf_ack); |
@@ -400,7 +400,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
400 | /* If the primary path is changing, assume that the | 400 | /* If the primary path is changing, assume that the |
401 | * user wants to use this new path. | 401 | * user wants to use this new path. |
402 | */ | 402 | */ |
403 | if (transport->active) | 403 | if (transport->state != SCTP_INACTIVE) |
404 | asoc->peer.active_path = transport; | 404 | asoc->peer.active_path = transport; |
405 | 405 | ||
406 | /* | 406 | /* |
@@ -428,10 +428,58 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; | 428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* Remove a transport from an association. */ | ||
432 | void sctp_assoc_rm_peer(struct sctp_association *asoc, | ||
433 | struct sctp_transport *peer) | ||
434 | { | ||
435 | struct list_head *pos; | ||
436 | struct sctp_transport *transport; | ||
437 | |||
438 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ", | ||
439 | " port: %d\n", | ||
440 | asoc, | ||
441 | (&peer->ipaddr), | ||
442 | peer->ipaddr.v4.sin_port); | ||
443 | |||
444 | /* If we are to remove the current retran_path, update it | ||
445 | * to the next peer before removing this peer from the list. | ||
446 | */ | ||
447 | if (asoc->peer.retran_path == peer) | ||
448 | sctp_assoc_update_retran_path(asoc); | ||
449 | |||
450 | /* Remove this peer from the list. */ | ||
451 | list_del(&peer->transports); | ||
452 | |||
453 | /* Get the first transport of asoc. */ | ||
454 | pos = asoc->peer.transport_addr_list.next; | ||
455 | transport = list_entry(pos, struct sctp_transport, transports); | ||
456 | |||
457 | /* Update any entries that match the peer to be deleted. */ | ||
458 | if (asoc->peer.primary_path == peer) | ||
459 | sctp_assoc_set_primary(asoc, transport); | ||
460 | if (asoc->peer.active_path == peer) | ||
461 | asoc->peer.active_path = transport; | ||
462 | if (asoc->peer.last_data_from == peer) | ||
463 | asoc->peer.last_data_from = transport; | ||
464 | |||
465 | /* If we remove the transport an INIT was last sent to, set it to | ||
466 | * NULL. Combined with the update of the retran path above, this | ||
467 | * will cause the next INIT to be sent to the next available | ||
468 | * transport, maintaining the cycle. | ||
469 | */ | ||
470 | if (asoc->init_last_sent_to == peer) | ||
471 | asoc->init_last_sent_to = NULL; | ||
472 | |||
473 | asoc->peer.transport_count--; | ||
474 | |||
475 | sctp_transport_free(peer); | ||
476 | } | ||
477 | |||
431 | /* Add a transport address to an association. */ | 478 | /* Add a transport address to an association. */ |
432 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | 479 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, |
433 | const union sctp_addr *addr, | 480 | const union sctp_addr *addr, |
434 | int gfp) | 481 | const int gfp, |
482 | const int peer_state) | ||
435 | { | 483 | { |
436 | struct sctp_transport *peer; | 484 | struct sctp_transport *peer; |
437 | struct sctp_sock *sp; | 485 | struct sctp_sock *sp; |
@@ -442,14 +490,25 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
442 | /* AF_INET and AF_INET6 share common port field. */ | 490 | /* AF_INET and AF_INET6 share common port field. */ |
443 | port = addr->v4.sin_port; | 491 | port = addr->v4.sin_port; |
444 | 492 | ||
493 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", | ||
494 | " port: %d state:%s\n", | ||
495 | asoc, | ||
496 | addr, | ||
497 | addr->v4.sin_port, | ||
498 | peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE"); | ||
499 | |||
445 | /* Set the port if it has not been set yet. */ | 500 | /* Set the port if it has not been set yet. */ |
446 | if (0 == asoc->peer.port) | 501 | if (0 == asoc->peer.port) |
447 | asoc->peer.port = port; | 502 | asoc->peer.port = port; |
448 | 503 | ||
449 | /* Check to see if this is a duplicate. */ | 504 | /* Check to see if this is a duplicate. */ |
450 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 505 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
451 | if (peer) | 506 | if (peer) { |
507 | if (peer_state == SCTP_ACTIVE && | ||
508 | peer->state == SCTP_UNKNOWN) | ||
509 | peer->state = SCTP_ACTIVE; | ||
452 | return peer; | 510 | return peer; |
511 | } | ||
453 | 512 | ||
454 | peer = sctp_transport_new(addr, gfp); | 513 | peer = sctp_transport_new(addr, gfp); |
455 | if (!peer) | 514 | if (!peer) |
@@ -516,8 +575,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
516 | /* Set the transport's RTO.initial value */ | 575 | /* Set the transport's RTO.initial value */ |
517 | peer->rto = asoc->rto_initial; | 576 | peer->rto = asoc->rto_initial; |
518 | 577 | ||
578 | /* Set the peer's active state. */ | ||
579 | peer->state = peer_state; | ||
580 | |||
519 | /* Attach the remote transport to our asoc. */ | 581 | /* Attach the remote transport to our asoc. */ |
520 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); | 582 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); |
583 | asoc->peer.transport_count++; | ||
521 | 584 | ||
522 | /* If we do not yet have a primary path, set one. */ | 585 | /* If we do not yet have a primary path, set one. */ |
523 | if (!asoc->peer.primary_path) { | 586 | if (!asoc->peer.primary_path) { |
@@ -525,8 +588,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
525 | asoc->peer.retran_path = peer; | 588 | asoc->peer.retran_path = peer; |
526 | } | 589 | } |
527 | 590 | ||
528 | if (asoc->peer.active_path == asoc->peer.retran_path) | 591 | if (asoc->peer.active_path == asoc->peer.retran_path) { |
529 | asoc->peer.retran_path = peer; | 592 | asoc->peer.retran_path = peer; |
593 | } | ||
530 | 594 | ||
531 | return peer; | 595 | return peer; |
532 | } | 596 | } |
@@ -537,37 +601,16 @@ void sctp_assoc_del_peer(struct sctp_association *asoc, | |||
537 | { | 601 | { |
538 | struct list_head *pos; | 602 | struct list_head *pos; |
539 | struct list_head *temp; | 603 | struct list_head *temp; |
540 | struct sctp_transport *peer = NULL; | ||
541 | struct sctp_transport *transport; | 604 | struct sctp_transport *transport; |
542 | 605 | ||
543 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 606 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
544 | transport = list_entry(pos, struct sctp_transport, transports); | 607 | transport = list_entry(pos, struct sctp_transport, transports); |
545 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { | 608 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { |
546 | peer = transport; | 609 | /* Do book keeping for removing the peer and free it. */ |
547 | list_del(pos); | 610 | sctp_assoc_rm_peer(asoc, transport); |
548 | break; | 611 | break; |
549 | } | 612 | } |
550 | } | 613 | } |
551 | |||
552 | /* The address we want delete is not in the association. */ | ||
553 | if (!peer) | ||
554 | return; | ||
555 | |||
556 | /* Get the first transport of asoc. */ | ||
557 | pos = asoc->peer.transport_addr_list.next; | ||
558 | transport = list_entry(pos, struct sctp_transport, transports); | ||
559 | |||
560 | /* Update any entries that match the peer to be deleted. */ | ||
561 | if (asoc->peer.primary_path == peer) | ||
562 | sctp_assoc_set_primary(asoc, transport); | ||
563 | if (asoc->peer.active_path == peer) | ||
564 | asoc->peer.active_path = transport; | ||
565 | if (asoc->peer.retran_path == peer) | ||
566 | asoc->peer.retran_path = transport; | ||
567 | if (asoc->peer.last_data_from == peer) | ||
568 | asoc->peer.last_data_from = transport; | ||
569 | |||
570 | sctp_transport_free(peer); | ||
571 | } | 614 | } |
572 | 615 | ||
573 | /* Lookup a transport by address. */ | 616 | /* Lookup a transport by address. */ |
@@ -608,12 +651,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
608 | /* Record the transition on the transport. */ | 651 | /* Record the transition on the transport. */ |
609 | switch (command) { | 652 | switch (command) { |
610 | case SCTP_TRANSPORT_UP: | 653 | case SCTP_TRANSPORT_UP: |
611 | transport->active = SCTP_ACTIVE; | 654 | transport->state = SCTP_ACTIVE; |
612 | spc_state = SCTP_ADDR_AVAILABLE; | 655 | spc_state = SCTP_ADDR_AVAILABLE; |
613 | break; | 656 | break; |
614 | 657 | ||
615 | case SCTP_TRANSPORT_DOWN: | 658 | case SCTP_TRANSPORT_DOWN: |
616 | transport->active = SCTP_INACTIVE; | 659 | transport->state = SCTP_INACTIVE; |
617 | spc_state = SCTP_ADDR_UNREACHABLE; | 660 | spc_state = SCTP_ADDR_UNREACHABLE; |
618 | break; | 661 | break; |
619 | 662 | ||
@@ -643,7 +686,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
643 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 686 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
644 | t = list_entry(pos, struct sctp_transport, transports); | 687 | t = list_entry(pos, struct sctp_transport, transports); |
645 | 688 | ||
646 | if (!t->active) | 689 | if (t->state == SCTP_INACTIVE) |
647 | continue; | 690 | continue; |
648 | if (!first || t->last_time_heard > first->last_time_heard) { | 691 | if (!first || t->last_time_heard > first->last_time_heard) { |
649 | second = first; | 692 | second = first; |
@@ -663,7 +706,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
663 | * [If the primary is active but not most recent, bump the most | 706 | * [If the primary is active but not most recent, bump the most |
664 | * recently used transport.] | 707 | * recently used transport.] |
665 | */ | 708 | */ |
666 | if (asoc->peer.primary_path->active && | 709 | if (asoc->peer.primary_path->state != SCTP_INACTIVE && |
667 | first != asoc->peer.primary_path) { | 710 | first != asoc->peer.primary_path) { |
668 | second = first; | 711 | second = first; |
669 | first = asoc->peer.primary_path; | 712 | first = asoc->peer.primary_path; |
@@ -958,7 +1001,7 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
958 | transports); | 1001 | transports); |
959 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) | 1002 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) |
960 | sctp_assoc_add_peer(asoc, &trans->ipaddr, | 1003 | sctp_assoc_add_peer(asoc, &trans->ipaddr, |
961 | GFP_ATOMIC); | 1004 | GFP_ATOMIC, SCTP_ACTIVE); |
962 | } | 1005 | } |
963 | 1006 | ||
964 | asoc->ctsn_ack_point = asoc->next_tsn - 1; | 1007 | asoc->ctsn_ack_point = asoc->next_tsn - 1; |
@@ -998,7 +1041,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
998 | 1041 | ||
999 | /* Try to find an active transport. */ | 1042 | /* Try to find an active transport. */ |
1000 | 1043 | ||
1001 | if (t->active) { | 1044 | if (t->state != SCTP_INACTIVE) { |
1002 | break; | 1045 | break; |
1003 | } else { | 1046 | } else { |
1004 | /* Keep track of the next transport in case | 1047 | /* Keep track of the next transport in case |
@@ -1019,6 +1062,40 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1019 | } | 1062 | } |
1020 | 1063 | ||
1021 | asoc->peer.retran_path = t; | 1064 | asoc->peer.retran_path = t; |
1065 | |||
1066 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
1067 | " %p addr: ", | ||
1068 | " port: %d\n", | ||
1069 | asoc, | ||
1070 | (&t->ipaddr), | ||
1071 | t->ipaddr.v4.sin_port); | ||
1072 | } | ||
1073 | |||
1074 | /* Choose the transport for sending a INIT packet. */ | ||
1075 | struct sctp_transport *sctp_assoc_choose_init_transport( | ||
1076 | struct sctp_association *asoc) | ||
1077 | { | ||
1078 | struct sctp_transport *t; | ||
1079 | |||
1080 | /* Use the retran path. If the last INIT was sent over the | ||
1081 | * retran path, update the retran path and use it. | ||
1082 | */ | ||
1083 | if (!asoc->init_last_sent_to) { | ||
1084 | t = asoc->peer.active_path; | ||
1085 | } else { | ||
1086 | if (asoc->init_last_sent_to == asoc->peer.retran_path) | ||
1087 | sctp_assoc_update_retran_path(asoc); | ||
1088 | t = asoc->peer.retran_path; | ||
1089 | } | ||
1090 | |||
1091 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
1092 | " %p addr: ", | ||
1093 | " port: %d\n", | ||
1094 | asoc, | ||
1095 | (&t->ipaddr), | ||
1096 | t->ipaddr.v4.sin_port); | ||
1097 | |||
1098 | return t; | ||
1022 | } | 1099 | } |
1023 | 1100 | ||
1024 | /* Choose the transport for sending a SHUTDOWN packet. */ | 1101 | /* Choose the transport for sending a SHUTDOWN packet. */ |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 334f61773e6d..2ec0320fac3b 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -134,7 +134,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
134 | ep->last_key = ep->current_key = 0; | 134 | ep->last_key = ep->current_key = 0; |
135 | ep->key_changed_at = jiffies; | 135 | ep->key_changed_at = jiffies; |
136 | 136 | ||
137 | ep->debug_name = "unnamedEndpoint"; | ||
138 | return ep; | 137 | return ep; |
139 | } | 138 | } |
140 | 139 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index fffc880a646d..339f7acfdb64 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -353,7 +353,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
353 | 353 | ||
354 | sctp_do_sm(SCTP_EVENT_T_OTHER, | 354 | sctp_do_sm(SCTP_EVENT_T_OTHER, |
355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | 355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), |
356 | asoc->state, asoc->ep, asoc, NULL, | 356 | asoc->state, asoc->ep, asoc, t, |
357 | GFP_ATOMIC); | 357 | GFP_ATOMIC); |
358 | 358 | ||
359 | } | 359 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 1b2d4adc4ddb..4eb81a1407b7 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -682,9 +682,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
682 | 682 | ||
683 | if (!new_transport) { | 683 | if (!new_transport) { |
684 | new_transport = asoc->peer.active_path; | 684 | new_transport = asoc->peer.active_path; |
685 | } else if (!new_transport->active) { | 685 | } else if (new_transport->state == SCTP_INACTIVE) { |
686 | /* If the chunk is Heartbeat or Heartbeat Ack, | 686 | /* If the chunk is Heartbeat or Heartbeat Ack, |
687 | * send it to chunk->transport, even if it's | 687 | * send it to chunk->transport, even if it's |
688 | * inactive. | 688 | * inactive. |
689 | * | 689 | * |
690 | * 3.3.6 Heartbeat Acknowledgement: | 690 | * 3.3.6 Heartbeat Acknowledgement: |
@@ -840,7 +840,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
840 | * Otherwise, we want to use the active path. | 840 | * Otherwise, we want to use the active path. |
841 | */ | 841 | */ |
842 | new_transport = chunk->transport; | 842 | new_transport = chunk->transport; |
843 | if (!new_transport || !new_transport->active) | 843 | if (!new_transport || |
844 | new_transport->state == SCTP_INACTIVE) | ||
844 | new_transport = asoc->peer.active_path; | 845 | new_transport = asoc->peer.active_path; |
845 | 846 | ||
846 | /* Change packets if necessary. */ | 847 | /* Change packets if necessary. */ |
@@ -1454,7 +1455,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1454 | /* Mark the destination transport address as | 1455 | /* Mark the destination transport address as |
1455 | * active if it is not so marked. | 1456 | * active if it is not so marked. |
1456 | */ | 1457 | */ |
1457 | if (!transport->active) { | 1458 | if (transport->state == SCTP_INACTIVE) { |
1458 | sctp_assoc_control_transport( | 1459 | sctp_assoc_control_transport( |
1459 | transport->asoc, | 1460 | transport->asoc, |
1460 | transport, | 1461 | transport, |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 33ac8bf47b0e..5baed9bb7de5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1830,7 +1830,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1830 | * be a a better choice than any of the embedded addresses. | 1830 | * be a a better choice than any of the embedded addresses. |
1831 | */ | 1831 | */ |
1832 | if (peer_addr) | 1832 | if (peer_addr) |
1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp)) | 1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) |
1834 | goto nomem; | 1834 | goto nomem; |
1835 | 1835 | ||
1836 | /* Process the initialization parameters. */ | 1836 | /* Process the initialization parameters. */ |
@@ -1841,6 +1841,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1841 | goto clean_up; | 1841 | goto clean_up; |
1842 | } | 1842 | } |
1843 | 1843 | ||
1844 | /* Walk list of transports, removing transports in the UNKNOWN state. */ | ||
1845 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | ||
1846 | transport = list_entry(pos, struct sctp_transport, transports); | ||
1847 | if (transport->state == SCTP_UNKNOWN) { | ||
1848 | sctp_assoc_rm_peer(asoc, transport); | ||
1849 | } | ||
1850 | } | ||
1851 | |||
1844 | /* The fixed INIT headers are always in network byte | 1852 | /* The fixed INIT headers are always in network byte |
1845 | * order. | 1853 | * order. |
1846 | */ | 1854 | */ |
@@ -1906,7 +1914,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1906 | * stream sequence number shall be set to 0. | 1914 | * stream sequence number shall be set to 0. |
1907 | */ | 1915 | */ |
1908 | 1916 | ||
1909 | /* Allocate storage for the negotiated streams if it is not a temporary * association. | 1917 | /* Allocate storage for the negotiated streams if it is not a temporary |
1918 | * association. | ||
1910 | */ | 1919 | */ |
1911 | if (!asoc->temp) { | 1920 | if (!asoc->temp) { |
1912 | int assoc_id; | 1921 | int assoc_id; |
@@ -1952,6 +1961,9 @@ clean_up: | |||
1952 | list_del_init(pos); | 1961 | list_del_init(pos); |
1953 | sctp_transport_free(transport); | 1962 | sctp_transport_free(transport); |
1954 | } | 1963 | } |
1964 | |||
1965 | asoc->peer.transport_count = 0; | ||
1966 | |||
1955 | nomem: | 1967 | nomem: |
1956 | return 0; | 1968 | return 0; |
1957 | } | 1969 | } |
@@ -1995,7 +2007,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
1995 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); | 2007 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); |
1996 | scope = sctp_scope(peer_addr); | 2008 | scope = sctp_scope(peer_addr); |
1997 | if (sctp_in_scope(&addr, scope)) | 2009 | if (sctp_in_scope(&addr, scope)) |
1998 | if (!sctp_assoc_add_peer(asoc, &addr, gfp)) | 2010 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE)) |
1999 | return 0; | 2011 | return 0; |
2000 | break; | 2012 | break; |
2001 | 2013 | ||
@@ -2396,7 +2408,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2396 | * Due to Resource Shortage'. | 2408 | * Due to Resource Shortage'. |
2397 | */ | 2409 | */ |
2398 | 2410 | ||
2399 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC); | 2411 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE); |
2400 | if (!peer) | 2412 | if (!peer) |
2401 | return SCTP_ERROR_RSRC_LOW; | 2413 | return SCTP_ERROR_RSRC_LOW; |
2402 | 2414 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index f65fa441952f..778639db125a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
414 | */ | 414 | */ |
415 | asoc->overall_error_count++; | 415 | asoc->overall_error_count++; |
416 | 416 | ||
417 | if (transport->active && | 417 | if (transport->state != SCTP_INACTIVE && |
418 | (transport->error_count++ >= transport->max_retrans)) { | 418 | (transport->error_count++ >= transport->max_retrans)) { |
419 | SCTP_DEBUG_PRINTK("transport_strike: transport " | 419 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", |
420 | "IP:%d.%d.%d.%d failed.\n", | 420 | " transport IP: port:%d failed.\n", |
421 | NIPQUAD(transport->ipaddr.v4.sin_addr)); | 421 | asoc, |
422 | (&transport->ipaddr), | ||
423 | transport->ipaddr.v4.sin_port); | ||
422 | sctp_assoc_control_transport(asoc, transport, | 424 | sctp_assoc_control_transport(asoc, transport, |
423 | SCTP_TRANSPORT_DOWN, | 425 | SCTP_TRANSPORT_DOWN, |
424 | SCTP_FAILED_THRESHOLD); | 426 | SCTP_FAILED_THRESHOLD); |
@@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
593 | /* Mark the destination transport address as active if it is not so | 595 | /* Mark the destination transport address as active if it is not so |
594 | * marked. | 596 | * marked. |
595 | */ | 597 | */ |
596 | if (!t->active) | 598 | if (t->state == SCTP_INACTIVE) |
597 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | 599 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, |
598 | SCTP_HEARTBEAT_SUCCESS); | 600 | SCTP_HEARTBEAT_SUCCESS); |
599 | 601 | ||
@@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
665 | 667 | ||
666 | asoc->state = state; | 668 | asoc->state = state; |
667 | 669 | ||
670 | SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n", | ||
671 | asoc, sctp_state_tbl[state]); | ||
672 | |||
668 | if (sctp_style(sk, TCP)) { | 673 | if (sctp_style(sk, TCP)) { |
669 | /* Change the sk->sk_state of a TCP-style socket that has | 674 | /* Change the sk->sk_state of a TCP-style socket that has |
670 | * sucessfully completed a connect() call. | 675 | * sucessfully completed a connect() call. |
671 | */ | 676 | */ |
672 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) | 677 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) |
@@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
678 | sk->sk_shutdown |= RCV_SHUTDOWN; | 683 | sk->sk_shutdown |= RCV_SHUTDOWN; |
679 | } | 684 | } |
680 | 685 | ||
686 | if (sctp_state(asoc, COOKIE_WAIT)) { | ||
687 | /* Reset init timeouts since they may have been | ||
688 | * increased due to timer expirations. | ||
689 | */ | ||
690 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
691 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]; | ||
692 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = | ||
693 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]; | ||
694 | } | ||
695 | |||
681 | if (sctp_state(asoc, ESTABLISHED) || | 696 | if (sctp_state(asoc, ESTABLISHED) || |
682 | sctp_state(asoc, CLOSED) || | 697 | sctp_state(asoc, CLOSED) || |
683 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { | 698 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { |
@@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1120 | * to be executed only during failed attempts of | 1135 | * to be executed only during failed attempts of |
1121 | * association establishment. | 1136 | * association establishment. |
1122 | */ | 1137 | */ |
1123 | if ((asoc->peer.retran_path != | 1138 | if ((asoc->peer.retran_path != |
1124 | asoc->peer.primary_path) && | 1139 | asoc->peer.primary_path) && |
1125 | (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) { | 1140 | (asoc->init_err_counter > 0)) { |
1126 | sctp_add_cmd_sf(commands, | 1141 | sctp_add_cmd_sf(commands, |
1127 | SCTP_CMD_FORCE_PRIM_RETRAN, | 1142 | SCTP_CMD_FORCE_PRIM_RETRAN, |
1128 | SCTP_NULL()); | 1143 | SCTP_NULL()); |
1129 | } | 1144 | } |
@@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1237 | sctp_association_put(asoc); | 1252 | sctp_association_put(asoc); |
1238 | break; | 1253 | break; |
1239 | 1254 | ||
1255 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: | ||
1256 | chunk = cmd->obj.ptr; | ||
1257 | t = sctp_assoc_choose_init_transport(asoc); | ||
1258 | asoc->init_last_sent_to = t; | ||
1259 | chunk->transport = t; | ||
1260 | t->init_sent_count++; | ||
1261 | break; | ||
1262 | |||
1240 | case SCTP_CMD_INIT_RESTART: | 1263 | case SCTP_CMD_INIT_RESTART: |
1241 | /* Do the needed accounting and updates | 1264 | /* Do the needed accounting and updates |
1242 | * associated with restarting an initialization | 1265 | * associated with restarting an initialization |
1243 | * timer. | 1266 | * timer. Only multiply the timeout by two if |
1267 | * all transports have been tried at the current | ||
1268 | * timeout. | ||
1269 | */ | ||
1270 | t = asoc->init_last_sent_to; | ||
1271 | asoc->init_err_counter++; | ||
1272 | |||
1273 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
1274 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; | ||
1275 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > | ||
1276 | asoc->max_init_timeo) { | ||
1277 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
1278 | asoc->max_init_timeo; | ||
1279 | } | ||
1280 | asoc->init_cycle++; | ||
1281 | SCTP_DEBUG_PRINTK( | ||
1282 | "T1 INIT Timeout adjustment" | ||
1283 | " init_err_counter: %d" | ||
1284 | " cycle: %d" | ||
1285 | " timeout: %d\n", | ||
1286 | asoc->init_err_counter, | ||
1287 | asoc->init_cycle, | ||
1288 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); | ||
1289 | } | ||
1290 | |||
1291 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | ||
1292 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
1293 | break; | ||
1294 | |||
1295 | case SCTP_CMD_COOKIEECHO_RESTART: | ||
1296 | /* Do the needed accounting and updates | ||
1297 | * associated with restarting an initialization | ||
1298 | * timer. Only multiply the timeout by two if | ||
1299 | * all transports have been tried at the current | ||
1300 | * timeout. | ||
1244 | */ | 1301 | */ |
1245 | asoc->counters[SCTP_COUNTER_INIT_ERROR]++; | 1302 | asoc->init_err_counter++; |
1246 | asoc->timeouts[cmd->obj.to] *= 2; | 1303 | |
1247 | if (asoc->timeouts[cmd->obj.to] > | 1304 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; |
1305 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > | ||
1248 | asoc->max_init_timeo) { | 1306 | asoc->max_init_timeo) { |
1249 | asoc->timeouts[cmd->obj.to] = | 1307 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = |
1250 | asoc->max_init_timeo; | 1308 | asoc->max_init_timeo; |
1251 | } | 1309 | } |
1310 | SCTP_DEBUG_PRINTK( | ||
1311 | "T1 COOKIE Timeout adjustment" | ||
1312 | " init_err_counter: %d" | ||
1313 | " timeout: %d\n", | ||
1314 | asoc->init_err_counter, | ||
1315 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); | ||
1252 | 1316 | ||
1253 | /* If we've sent any data bundled with | 1317 | /* If we've sent any data bundled with |
1254 | * COOKIE-ECHO we need to resend. | 1318 | * COOKIE-ECHO we need to resend. |
@@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1261 | 1325 | ||
1262 | sctp_add_cmd_sf(commands, | 1326 | sctp_add_cmd_sf(commands, |
1263 | SCTP_CMD_TIMER_RESTART, | 1327 | SCTP_CMD_TIMER_RESTART, |
1264 | SCTP_TO(cmd->obj.to)); | 1328 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
1265 | break; | 1329 | break; |
1266 | 1330 | ||
1267 | case SCTP_CMD_INIT_FAILED: | 1331 | case SCTP_CMD_INIT_FAILED: |
@@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1273 | subtype, chunk, cmd->obj.u32); | 1337 | subtype, chunk, cmd->obj.u32); |
1274 | break; | 1338 | break; |
1275 | 1339 | ||
1276 | case SCTP_CMD_COUNTER_INC: | 1340 | case SCTP_CMD_INIT_COUNTER_INC: |
1277 | asoc->counters[cmd->obj.counter]++; | 1341 | asoc->init_err_counter++; |
1278 | break; | 1342 | break; |
1279 | 1343 | ||
1280 | case SCTP_CMD_COUNTER_RESET: | 1344 | case SCTP_CMD_INIT_COUNTER_RESET: |
1281 | asoc->counters[cmd->obj.counter] = 0; | 1345 | asoc->init_err_counter = 0; |
1346 | asoc->init_cycle = 0; | ||
1282 | break; | 1347 | break; |
1283 | 1348 | ||
1284 | case SCTP_CMD_REPORT_DUP: | 1349 | case SCTP_CMD_REPORT_DUP: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8e01b8f09ac2..058189684c7c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -533,6 +533,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, | 533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, |
534 | SCTP_PEER_INIT(initchunk)); | 534 | SCTP_PEER_INIT(initchunk)); |
535 | 535 | ||
536 | /* Reset init error count upon receipt of INIT-ACK. */ | ||
537 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); | ||
538 | |||
536 | /* 5.1 C) "A" shall stop the T1-init timer and leave | 539 | /* 5.1 C) "A" shall stop the T1-init timer and leave |
537 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie | 540 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie |
538 | * timer, and enter the COOKIE-ECHOED state. | 541 | * 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, | |||
775 | * from the COOKIE-ECHOED state to the COOKIE-WAIT | 778 | * from the COOKIE-ECHOED state to the COOKIE-WAIT |
776 | * state is performed. | 779 | * state is performed. |
777 | */ | 780 | */ |
778 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET, | 781 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); |
779 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
780 | 782 | ||
781 | /* RFC 2960 5.1 Normal Establishment of an Association | 783 | /* RFC 2960 5.1 Normal Establishment of an Association |
782 | * | 784 | * |
@@ -1019,10 +1021,22 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1019 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); | 1021 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); |
1020 | 1022 | ||
1021 | /* This should never happen, but lets log it if so. */ | 1023 | /* This should never happen, but lets log it if so. */ |
1022 | if (!link) { | 1024 | if (unlikely(!link)) { |
1023 | printk(KERN_WARNING | 1025 | if (from_addr.sa.sa_family == AF_INET6) { |
1024 | "%s: Could not find address %d.%d.%d.%d\n", | 1026 | printk(KERN_WARNING |
1025 | __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr)); | 1027 | "%s association %p could not find address " |
1028 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
1029 | __FUNCTION__, | ||
1030 | asoc, | ||
1031 | NIP6(from_addr.v6.sin6_addr)); | ||
1032 | } else { | ||
1033 | printk(KERN_WARNING | ||
1034 | "%s association %p could not find address " | ||
1035 | "%u.%u.%u.%u\n", | ||
1036 | __FUNCTION__, | ||
1037 | asoc, | ||
1038 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); | ||
1039 | } | ||
1026 | return SCTP_DISPOSITION_DISCARD; | 1040 | return SCTP_DISPOSITION_DISCARD; |
1027 | } | 1041 | } |
1028 | 1042 | ||
@@ -2095,9 +2109,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
2095 | sctp_errhdr_t *err; | 2109 | sctp_errhdr_t *err; |
2096 | struct sctp_chunk *reply; | 2110 | struct sctp_chunk *reply; |
2097 | struct sctp_bind_addr *bp; | 2111 | struct sctp_bind_addr *bp; |
2098 | int attempts; | 2112 | int attempts = asoc->init_err_counter + 1; |
2099 | |||
2100 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
2101 | 2113 | ||
2102 | if (attempts >= asoc->max_init_attempts) { | 2114 | if (attempts >= asoc->max_init_attempts) { |
2103 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2115 | 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, | |||
2157 | /* Cast away the const modifier, as we want to just | 2169 | /* Cast away the const modifier, as we want to just |
2158 | * rerun it through as a sideffect. | 2170 | * rerun it through as a sideffect. |
2159 | */ | 2171 | */ |
2160 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC, | 2172 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL()); |
2161 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
2162 | 2173 | ||
2163 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2174 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2164 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 2175 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
@@ -2281,8 +2292,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2281 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2292 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
2282 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2293 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2283 | 2294 | ||
2284 | sctp_stop_t1_and_abort(commands, error); | 2295 | return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport); |
2285 | return SCTP_DISPOSITION_ABORT; | ||
2286 | } | 2296 | } |
2287 | 2297 | ||
2288 | /* | 2298 | /* |
@@ -2294,8 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep | |||
2294 | void *arg, | 2304 | void *arg, |
2295 | sctp_cmd_seq_t *commands) | 2305 | sctp_cmd_seq_t *commands) |
2296 | { | 2306 | { |
2297 | sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR); | 2307 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc, |
2298 | return SCTP_DISPOSITION_ABORT; | 2308 | (struct sctp_transport *)arg); |
2299 | } | 2309 | } |
2300 | 2310 | ||
2301 | /* | 2311 | /* |
@@ -2318,8 +2328,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
2318 | * | 2328 | * |
2319 | * This is common code called by several sctp_sf_*_abort() functions above. | 2329 | * This is common code called by several sctp_sf_*_abort() functions above. |
2320 | */ | 2330 | */ |
2321 | void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | 2331 | sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
2332 | __u16 error, | ||
2333 | const struct sctp_association *asoc, | ||
2334 | struct sctp_transport *transport) | ||
2322 | { | 2335 | { |
2336 | SCTP_DEBUG_PRINTK("ABORT received (INIT).\n"); | ||
2323 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 2337 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
2324 | SCTP_STATE(SCTP_STATE_CLOSED)); | 2338 | SCTP_STATE(SCTP_STATE_CLOSED)); |
2325 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2339 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -2328,6 +2342,7 @@ void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | |||
2328 | /* CMD_INIT_FAILED will DELETE_TCB. */ | 2342 | /* CMD_INIT_FAILED will DELETE_TCB. */ |
2329 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2343 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
2330 | SCTP_U32(error)); | 2344 | SCTP_U32(error)); |
2345 | return SCTP_DISPOSITION_ABORT; | ||
2331 | } | 2346 | } |
2332 | 2347 | ||
2333 | /* | 2348 | /* |
@@ -3805,6 +3820,10 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, | |||
3805 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, | 3820 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, |
3806 | SCTP_ASOC((struct sctp_association *) asoc)); | 3821 | SCTP_ASOC((struct sctp_association *) asoc)); |
3807 | 3822 | ||
3823 | /* Choose transport for INIT. */ | ||
3824 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
3825 | SCTP_CHUNK(repl)); | ||
3826 | |||
3808 | /* After sending the INIT, "A" starts the T1-init timer and | 3827 | /* After sending the INIT, "A" starts the T1-init timer and |
3809 | * enters the COOKIE-WAIT state. | 3828 | * enters the COOKIE-WAIT state. |
3810 | */ | 3829 | */ |
@@ -4589,7 +4608,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
4589 | } | 4608 | } |
4590 | 4609 | ||
4591 | /* | 4610 | /* |
4592 | * sctp_sf_t1_timer_expire | 4611 | * sctp_sf_t1_init_timer_expire |
4593 | * | 4612 | * |
4594 | * Section: 4 Note: 2 | 4613 | * Section: 4 Note: 2 |
4595 | * Verification Tag: | 4614 | * Verification Tag: |
@@ -4603,7 +4622,59 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
4603 | * endpoint MUST abort the initialization process and report the | 4622 | * endpoint MUST abort the initialization process and report the |
4604 | * error to SCTP user. | 4623 | * error to SCTP user. |
4605 | * | 4624 | * |
4606 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | 4625 | * Outputs |
4626 | * (timers, events) | ||
4627 | * | ||
4628 | */ | ||
4629 | sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | ||
4630 | const struct sctp_association *asoc, | ||
4631 | const sctp_subtype_t type, | ||
4632 | void *arg, | ||
4633 | sctp_cmd_seq_t *commands) | ||
4634 | { | ||
4635 | struct sctp_chunk *repl = NULL; | ||
4636 | struct sctp_bind_addr *bp; | ||
4637 | int attempts = asoc->init_err_counter + 1; | ||
4638 | |||
4639 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); | ||
4640 | |||
4641 | if (attempts < asoc->max_init_attempts) { | ||
4642 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
4643 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
4644 | if (!repl) | ||
4645 | return SCTP_DISPOSITION_NOMEM; | ||
4646 | |||
4647 | /* Choose transport for INIT. */ | ||
4648 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
4649 | SCTP_CHUNK(repl)); | ||
4650 | |||
4651 | /* Issue a sideeffect to do the needed accounting. */ | ||
4652 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | ||
4653 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
4654 | |||
4655 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
4656 | } else { | ||
4657 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" | ||
4658 | " max_init_attempts: %d\n", | ||
4659 | attempts, asoc->max_init_attempts); | ||
4660 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | ||
4661 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | ||
4662 | return SCTP_DISPOSITION_DELETE_TCB; | ||
4663 | } | ||
4664 | |||
4665 | return SCTP_DISPOSITION_CONSUME; | ||
4666 | } | ||
4667 | |||
4668 | /* | ||
4669 | * sctp_sf_t1_cookie_timer_expire | ||
4670 | * | ||
4671 | * Section: 4 Note: 2 | ||
4672 | * Verification Tag: | ||
4673 | * Inputs | ||
4674 | * (endpoint, asoc) | ||
4675 | * | ||
4676 | * RFC 2960 Section 4 Notes | ||
4677 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | ||
4607 | * COOKIE ECHO and re-start the T1-cookie timer without changing | 4678 | * COOKIE ECHO and re-start the T1-cookie timer without changing |
4608 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. | 4679 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. |
4609 | * After that, the endpoint MUST abort the initialization process and | 4680 | * 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, | |||
4613 | * (timers, events) | 4684 | * (timers, events) |
4614 | * | 4685 | * |
4615 | */ | 4686 | */ |
4616 | sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep, | 4687 | sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep, |
4617 | const struct sctp_association *asoc, | 4688 | const struct sctp_association *asoc, |
4618 | const sctp_subtype_t type, | 4689 | const sctp_subtype_t type, |
4619 | void *arg, | 4690 | void *arg, |
4620 | sctp_cmd_seq_t *commands) | 4691 | sctp_cmd_seq_t *commands) |
4621 | { | 4692 | { |
4622 | struct sctp_chunk *repl; | 4693 | struct sctp_chunk *repl = NULL; |
4623 | struct sctp_bind_addr *bp; | 4694 | int attempts = asoc->init_err_counter + 1; |
4624 | sctp_event_timeout_t timer = (sctp_event_timeout_t) arg; | ||
4625 | int timeout; | ||
4626 | int attempts; | ||
4627 | |||
4628 | timeout = asoc->timeouts[timer]; | ||
4629 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
4630 | repl = NULL; | ||
4631 | 4695 | ||
4632 | SCTP_DEBUG_PRINTK("Timer T1 expired.\n"); | 4696 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); |
4633 | 4697 | ||
4634 | if (attempts < asoc->max_init_attempts) { | 4698 | if (attempts < asoc->max_init_attempts) { |
4635 | switch (timer) { | 4699 | repl = sctp_make_cookie_echo(asoc, NULL); |
4636 | case SCTP_EVENT_TIMEOUT_T1_INIT: | ||
4637 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
4638 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
4639 | break; | ||
4640 | |||
4641 | case SCTP_EVENT_TIMEOUT_T1_COOKIE: | ||
4642 | repl = sctp_make_cookie_echo(asoc, NULL); | ||
4643 | break; | ||
4644 | |||
4645 | default: | ||
4646 | BUG(); | ||
4647 | break; | ||
4648 | }; | ||
4649 | |||
4650 | if (!repl) | 4700 | if (!repl) |
4651 | goto nomem; | 4701 | return SCTP_DISPOSITION_NOMEM; |
4652 | 4702 | ||
4653 | /* Issue a sideeffect to do the needed accounting. */ | 4703 | /* Issue a sideeffect to do the needed accounting. */ |
4654 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | 4704 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, |
4655 | SCTP_TO(timer)); | 4705 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
4706 | |||
4656 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 4707 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
4657 | } else { | 4708 | } else { |
4658 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4709 | 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, | |||
4661 | } | 4712 | } |
4662 | 4713 | ||
4663 | return SCTP_DISPOSITION_CONSUME; | 4714 | return SCTP_DISPOSITION_CONSUME; |
4664 | |||
4665 | nomem: | ||
4666 | return SCTP_DISPOSITION_NOMEM; | ||
4667 | } | 4715 | } |
4668 | 4716 | ||
4669 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN | 4717 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 8967846f69e8..75ef10408764 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -783,7 +783,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
783 | /* SCTP_STATE_COOKIE_WAIT */ \ | 783 | /* SCTP_STATE_COOKIE_WAIT */ \ |
784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ | 784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ |
785 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 785 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
786 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 786 | {.fn = sctp_sf_t1_cookie_timer_expire, \ |
787 | .name = "sctp_sf_t1_cookie_timer_expire"}, \ | ||
787 | /* SCTP_STATE_ESTABLISHED */ \ | 788 | /* SCTP_STATE_ESTABLISHED */ \ |
788 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 789 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
789 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 790 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
@@ -802,7 +803,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
802 | /* SCTP_STATE_CLOSED */ \ | 803 | /* SCTP_STATE_CLOSED */ \ |
803 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 804 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
804 | /* SCTP_STATE_COOKIE_WAIT */ \ | 805 | /* SCTP_STATE_COOKIE_WAIT */ \ |
805 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 806 | {.fn = sctp_sf_t1_init_timer_expire, \ |
807 | .name = "sctp_sf_t1_init_timer_expire"}, \ | ||
806 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 808 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
807 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 809 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
808 | /* SCTP_STATE_ESTABLISHED */ \ | 810 | /* SCTP_STATE_ESTABLISHED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e6926cb19420..aad55dc3792b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, | |||
262 | * sockaddr_in6 [RFC 2553]), | 262 | * sockaddr_in6 [RFC 2553]), |
263 | * addr_len - the size of the address structure. | 263 | * addr_len - the size of the address structure. |
264 | */ | 264 | */ |
265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) |
266 | { | 266 | { |
267 | int retval = 0; | 267 | int retval = 0; |
268 | 268 | ||
269 | sctp_lock_sock(sk); | 269 | sctp_lock_sock(sk); |
270 | 270 | ||
271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n", | 271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n", |
272 | sk, uaddr, addr_len); | 272 | sk, addr, addr_len); |
273 | 273 | ||
274 | /* Disallow binding twice. */ | 274 | /* Disallow binding twice. */ |
275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) | 275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) |
276 | retval = sctp_do_bind(sk, (union sctp_addr *)uaddr, | 276 | retval = sctp_do_bind(sk, (union sctp_addr *)addr, |
277 | addr_len); | 277 | addr_len); |
278 | else | 278 | else |
279 | retval = -EINVAL; | 279 | retval = -EINVAL; |
@@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
318 | unsigned short snum; | 318 | unsigned short snum; |
319 | int ret = 0; | 319 | int ret = 0; |
320 | 320 | ||
321 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n", | ||
322 | sk, addr, len); | ||
323 | |||
324 | /* Common sockaddr verification. */ | 321 | /* Common sockaddr verification. */ |
325 | af = sctp_sockaddr_af(sp, addr, len); | 322 | af = sctp_sockaddr_af(sp, addr, len); |
326 | if (!af) | 323 | if (!af) { |
324 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n", | ||
325 | sk, addr, len); | ||
327 | return -EINVAL; | 326 | return -EINVAL; |
327 | } | ||
328 | |||
329 | snum = ntohs(addr->v4.sin_port); | ||
330 | |||
331 | SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ", | ||
332 | ", port: %d, new port: %d, len: %d)\n", | ||
333 | sk, | ||
334 | addr, | ||
335 | bp->port, snum, | ||
336 | len); | ||
328 | 337 | ||
329 | /* PF specific bind() address verification. */ | 338 | /* PF specific bind() address verification. */ |
330 | if (!sp->pf->bind_verify(sp, addr)) | 339 | if (!sp->pf->bind_verify(sp, addr)) |
331 | return -EADDRNOTAVAIL; | 340 | return -EADDRNOTAVAIL; |
332 | 341 | ||
333 | snum= ntohs(addr->v4.sin_port); | ||
334 | |||
335 | SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n", | ||
336 | bp->port, snum); | ||
337 | |||
338 | /* We must either be unbound, or bind to the same port. */ | 342 | /* We must either be unbound, or bind to the same port. */ |
339 | if (bp->port && (snum != bp->port)) { | 343 | if (bp->port && (snum != bp->port)) { |
340 | SCTP_DEBUG_PRINTK("sctp_do_bind:" | 344 | SCTP_DEBUG_PRINTK("sctp_do_bind:" |
@@ -816,7 +820,8 @@ out: | |||
816 | * | 820 | * |
817 | * Basically do nothing but copying the addresses from user to kernel | 821 | * Basically do nothing but copying the addresses from user to kernel |
818 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. | 822 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. |
819 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. | 823 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() |
824 | * from userspace. | ||
820 | * | 825 | * |
821 | * We don't use copy_from_user() for optimization: we first do the | 826 | * We don't use copy_from_user() for optimization: we first do the |
822 | * sanity checks (buffer size -fast- and access check-healthy | 827 | * sanity checks (buffer size -fast- and access check-healthy |
@@ -913,6 +918,243 @@ out: | |||
913 | return err; | 918 | return err; |
914 | } | 919 | } |
915 | 920 | ||
921 | /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) | ||
922 | * | ||
923 | * Common routine for handling connect() and sctp_connectx(). | ||
924 | * Connect will come in with just a single address. | ||
925 | */ | ||
926 | static int __sctp_connect(struct sock* sk, | ||
927 | struct sockaddr *kaddrs, | ||
928 | int addrs_size) | ||
929 | { | ||
930 | struct sctp_sock *sp; | ||
931 | struct sctp_endpoint *ep; | ||
932 | struct sctp_association *asoc = NULL; | ||
933 | struct sctp_association *asoc2; | ||
934 | struct sctp_transport *transport; | ||
935 | union sctp_addr to; | ||
936 | struct sctp_af *af; | ||
937 | sctp_scope_t scope; | ||
938 | long timeo; | ||
939 | int err = 0; | ||
940 | int addrcnt = 0; | ||
941 | int walk_size = 0; | ||
942 | struct sockaddr *sa_addr; | ||
943 | void *addr_buf; | ||
944 | |||
945 | sp = sctp_sk(sk); | ||
946 | ep = sp->ep; | ||
947 | |||
948 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
949 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
950 | * is already connected. | ||
951 | * It cannot be done even on a TCP-style listening socket. | ||
952 | */ | ||
953 | if (sctp_sstate(sk, ESTABLISHED) || | ||
954 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
955 | err = -EISCONN; | ||
956 | goto out_free; | ||
957 | } | ||
958 | |||
959 | /* Walk through the addrs buffer and count the number of addresses. */ | ||
960 | addr_buf = kaddrs; | ||
961 | while (walk_size < addrs_size) { | ||
962 | sa_addr = (struct sockaddr *)addr_buf; | ||
963 | af = sctp_get_af_specific(sa_addr->sa_family); | ||
964 | |||
965 | /* If the address family is not supported or if this address | ||
966 | * causes the address buffer to overflow return EINVAL. | ||
967 | */ | ||
968 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { | ||
969 | err = -EINVAL; | ||
970 | goto out_free; | ||
971 | } | ||
972 | |||
973 | err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr, | ||
974 | af->sockaddr_len); | ||
975 | if (err) | ||
976 | goto out_free; | ||
977 | |||
978 | memcpy(&to, sa_addr, af->sockaddr_len); | ||
979 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
980 | |||
981 | /* Check if there already is a matching association on the | ||
982 | * endpoint (other than the one created here). | ||
983 | */ | ||
984 | asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
985 | if (asoc2 && asoc2 != asoc) { | ||
986 | if (asoc2->state >= SCTP_STATE_ESTABLISHED) | ||
987 | err = -EISCONN; | ||
988 | else | ||
989 | err = -EALREADY; | ||
990 | goto out_free; | ||
991 | } | ||
992 | |||
993 | /* If we could not find a matching association on the endpoint, | ||
994 | * make sure that there is no peeled-off association matching | ||
995 | * the peer address even on another socket. | ||
996 | */ | ||
997 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
998 | err = -EADDRNOTAVAIL; | ||
999 | goto out_free; | ||
1000 | } | ||
1001 | |||
1002 | if (!asoc) { | ||
1003 | /* If a bind() or sctp_bindx() is not called prior to | ||
1004 | * an sctp_connectx() call, the system picks an | ||
1005 | * ephemeral port and will choose an address set | ||
1006 | * equivalent to binding with a wildcard address. | ||
1007 | */ | ||
1008 | if (!ep->base.bind_addr.port) { | ||
1009 | if (sctp_autobind(sk)) { | ||
1010 | err = -EAGAIN; | ||
1011 | goto out_free; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | scope = sctp_scope(&to); | ||
1016 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
1017 | if (!asoc) { | ||
1018 | err = -ENOMEM; | ||
1019 | goto out_free; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | /* Prime the peer's transport structures. */ | ||
1024 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, | ||
1025 | SCTP_UNKNOWN); | ||
1026 | if (!transport) { | ||
1027 | err = -ENOMEM; | ||
1028 | goto out_free; | ||
1029 | } | ||
1030 | |||
1031 | addrcnt++; | ||
1032 | addr_buf += af->sockaddr_len; | ||
1033 | walk_size += af->sockaddr_len; | ||
1034 | } | ||
1035 | |||
1036 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | ||
1037 | if (err < 0) { | ||
1038 | goto out_free; | ||
1039 | } | ||
1040 | |||
1041 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
1042 | if (err < 0) { | ||
1043 | goto out_free; | ||
1044 | } | ||
1045 | |||
1046 | /* Initialize sk's dport and daddr for getpeername() */ | ||
1047 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
1048 | af = sctp_get_af_specific(to.sa.sa_family); | ||
1049 | af->to_sk_daddr(&to, sk); | ||
1050 | |||
1051 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
1052 | err = sctp_wait_for_connect(asoc, &timeo); | ||
1053 | |||
1054 | /* Don't free association on exit. */ | ||
1055 | asoc = NULL; | ||
1056 | |||
1057 | out_free: | ||
1058 | |||
1059 | SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" | ||
1060 | " kaddrs: %p err: %d\n", | ||
1061 | asoc, kaddrs, err); | ||
1062 | if (asoc) | ||
1063 | sctp_association_free(asoc); | ||
1064 | return err; | ||
1065 | } | ||
1066 | |||
1067 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() | ||
1068 | * | ||
1069 | * API 8.9 | ||
1070 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); | ||
1071 | * | ||
1072 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. | ||
1073 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 | ||
1074 | * or IPv6 addresses. | ||
1075 | * | ||
1076 | * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see | ||
1077 | * Section 3.1.2 for this usage. | ||
1078 | * | ||
1079 | * addrs is a pointer to an array of one or more socket addresses. Each | ||
1080 | * address is contained in its appropriate structure (i.e. struct | ||
1081 | * sockaddr_in or struct sockaddr_in6) the family of the address type | ||
1082 | * must be used to distengish the address length (note that this | ||
1083 | * representation is termed a "packed array" of addresses). The caller | ||
1084 | * specifies the number of addresses in the array with addrcnt. | ||
1085 | * | ||
1086 | * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns | ||
1087 | * -1, and sets errno to the appropriate error code. | ||
1088 | * | ||
1089 | * For SCTP, the port given in each socket address must be the same, or | ||
1090 | * sctp_connectx() will fail, setting errno to EINVAL. | ||
1091 | * | ||
1092 | * An application can use sctp_connectx to initiate an association with | ||
1093 | * an endpoint that is multi-homed. Much like sctp_bindx() this call | ||
1094 | * allows a caller to specify multiple addresses at which a peer can be | ||
1095 | * reached. The way the SCTP stack uses the list of addresses to set up | ||
1096 | * the association is implementation dependant. This function only | ||
1097 | * specifies that the stack will try to make use of all the addresses in | ||
1098 | * the list when needed. | ||
1099 | * | ||
1100 | * Note that the list of addresses passed in is only used for setting up | ||
1101 | * the association. It does not necessarily equal the set of addresses | ||
1102 | * the peer uses for the resulting association. If the caller wants to | ||
1103 | * find out the set of peer addresses, it must use sctp_getpaddrs() to | ||
1104 | * retrieve them after the association has been set up. | ||
1105 | * | ||
1106 | * Basically do nothing but copying the addresses from user to kernel | ||
1107 | * land and invoking either sctp_connectx(). This is used for tunneling | ||
1108 | * the sctp_connectx() request through sctp_setsockopt() from userspace. | ||
1109 | * | ||
1110 | * We don't use copy_from_user() for optimization: we first do the | ||
1111 | * sanity checks (buffer size -fast- and access check-healthy | ||
1112 | * pointer); if all of those succeed, then we can alloc the memory | ||
1113 | * (expensive operation) needed to copy the data to kernel. Then we do | ||
1114 | * the copying without checking the user space area | ||
1115 | * (__copy_from_user()). | ||
1116 | * | ||
1117 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does | ||
1118 | * it. | ||
1119 | * | ||
1120 | * sk The sk of the socket | ||
1121 | * addrs The pointer to the addresses in user land | ||
1122 | * addrssize Size of the addrs buffer | ||
1123 | * | ||
1124 | * Returns 0 if ok, <0 errno code on error. | ||
1125 | */ | ||
1126 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | ||
1127 | struct sockaddr __user *addrs, | ||
1128 | int addrs_size) | ||
1129 | { | ||
1130 | int err = 0; | ||
1131 | struct sockaddr *kaddrs; | ||
1132 | |||
1133 | SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n", | ||
1134 | __FUNCTION__, sk, addrs, addrs_size); | ||
1135 | |||
1136 | if (unlikely(addrs_size <= 0)) | ||
1137 | return -EINVAL; | ||
1138 | |||
1139 | /* Check the user passed a healthy pointer. */ | ||
1140 | if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) | ||
1141 | return -EFAULT; | ||
1142 | |||
1143 | /* Alloc space for the address array in kernel memory. */ | ||
1144 | kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); | ||
1145 | if (unlikely(!kaddrs)) | ||
1146 | return -ENOMEM; | ||
1147 | |||
1148 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | ||
1149 | err = -EFAULT; | ||
1150 | } else { | ||
1151 | err = __sctp_connect(sk, kaddrs, addrs_size); | ||
1152 | } | ||
1153 | |||
1154 | kfree(kaddrs); | ||
1155 | return err; | ||
1156 | } | ||
1157 | |||
916 | /* API 3.1.4 close() - UDP Style Syntax | 1158 | /* API 3.1.4 close() - UDP Style Syntax |
917 | * Applications use close() to perform graceful shutdown (as described in | 1159 | * Applications use close() to perform graceful shutdown (as described in |
918 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1160 | * 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, | |||
1095 | sp = sctp_sk(sk); | 1337 | sp = sctp_sk(sk); |
1096 | ep = sp->ep; | 1338 | ep = sp->ep; |
1097 | 1339 | ||
1098 | SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name); | 1340 | SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep); |
1099 | 1341 | ||
1100 | /* We cannot send a message over a TCP-style listening socket. */ | 1342 | /* We cannot send a message over a TCP-style listening socket. */ |
1101 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { | 1343 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { |
@@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1306 | } | 1548 | } |
1307 | 1549 | ||
1308 | /* Prime the peer's transport structures. */ | 1550 | /* Prime the peer's transport structures. */ |
1309 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 1551 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); |
1310 | if (!transport) { | 1552 | if (!transport) { |
1311 | err = -ENOMEM; | 1553 | err = -ENOMEM; |
1312 | goto out_free; | 1554 | goto out_free; |
@@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
2208 | optlen, SCTP_BINDX_REM_ADDR); | 2450 | optlen, SCTP_BINDX_REM_ADDR); |
2209 | break; | 2451 | break; |
2210 | 2452 | ||
2453 | case SCTP_SOCKOPT_CONNECTX: | ||
2454 | /* 'optlen' is the size of the addresses buffer. */ | ||
2455 | retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, | ||
2456 | optlen); | ||
2457 | break; | ||
2458 | |||
2211 | case SCTP_DISABLE_FRAGMENTS: | 2459 | case SCTP_DISABLE_FRAGMENTS: |
2212 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); | 2460 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); |
2213 | break; | 2461 | break; |
@@ -2283,112 +2531,29 @@ out_nounlock: | |||
2283 | * | 2531 | * |
2284 | * len: the size of the address. | 2532 | * len: the size of the address. |
2285 | */ | 2533 | */ |
2286 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, | 2534 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, |
2287 | int addr_len) | 2535 | int addr_len) |
2288 | { | 2536 | { |
2289 | struct sctp_sock *sp; | ||
2290 | struct sctp_endpoint *ep; | ||
2291 | struct sctp_association *asoc; | ||
2292 | struct sctp_transport *transport; | ||
2293 | union sctp_addr to; | ||
2294 | struct sctp_af *af; | ||
2295 | sctp_scope_t scope; | ||
2296 | long timeo; | ||
2297 | int err = 0; | 2537 | int err = 0; |
2538 | struct sctp_af *af; | ||
2298 | 2539 | ||
2299 | sctp_lock_sock(sk); | 2540 | sctp_lock_sock(sk); |
2300 | 2541 | ||
2301 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n", | 2542 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n", |
2302 | __FUNCTION__, sk, uaddr, addr_len); | 2543 | __FUNCTION__, sk, addr, addr_len); |
2303 | |||
2304 | sp = sctp_sk(sk); | ||
2305 | ep = sp->ep; | ||
2306 | |||
2307 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
2308 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
2309 | * is already connected. | ||
2310 | * It cannot be done even on a TCP-style listening socket. | ||
2311 | */ | ||
2312 | if (sctp_sstate(sk, ESTABLISHED) || | ||
2313 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
2314 | err = -EISCONN; | ||
2315 | goto out_unlock; | ||
2316 | } | ||
2317 | |||
2318 | err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len); | ||
2319 | if (err) | ||
2320 | goto out_unlock; | ||
2321 | |||
2322 | if (addr_len > sizeof(to)) | ||
2323 | addr_len = sizeof(to); | ||
2324 | memcpy(&to, uaddr, addr_len); | ||
2325 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
2326 | |||
2327 | asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
2328 | if (asoc) { | ||
2329 | if (asoc->state >= SCTP_STATE_ESTABLISHED) | ||
2330 | err = -EISCONN; | ||
2331 | else | ||
2332 | err = -EALREADY; | ||
2333 | goto out_unlock; | ||
2334 | } | ||
2335 | |||
2336 | /* If we could not find a matching association on the endpoint, | ||
2337 | * make sure that there is no peeled-off association matching the | ||
2338 | * peer address even on another socket. | ||
2339 | */ | ||
2340 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
2341 | err = -EADDRNOTAVAIL; | ||
2342 | goto out_unlock; | ||
2343 | } | ||
2344 | |||
2345 | /* If a bind() or sctp_bindx() is not called prior to a connect() | ||
2346 | * call, the system picks an ephemeral port and will choose an address | ||
2347 | * set equivalent to binding with a wildcard address. | ||
2348 | */ | ||
2349 | if (!ep->base.bind_addr.port) { | ||
2350 | if (sctp_autobind(sk)) { | ||
2351 | err = -EAGAIN; | ||
2352 | goto out_unlock; | ||
2353 | } | ||
2354 | } | ||
2355 | |||
2356 | scope = sctp_scope(&to); | ||
2357 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
2358 | if (!asoc) { | ||
2359 | err = -ENOMEM; | ||
2360 | goto out_unlock; | ||
2361 | } | ||
2362 | 2544 | ||
2363 | /* Prime the peer's transport structures. */ | 2545 | /* Validate addr_len before calling common connect/connectx routine. */ |
2364 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 2546 | af = sctp_get_af_specific(addr->sa_family); |
2365 | if (!transport) { | 2547 | if (!af || addr_len < af->sockaddr_len) { |
2366 | sctp_association_free(asoc); | 2548 | err = -EINVAL; |
2367 | goto out_unlock; | 2549 | } else { |
2368 | } | 2550 | /* Pass correct addr len to common routine (so it knows there |
2369 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | 2551 | * is only one address being passed. |
2370 | if (err < 0) { | 2552 | */ |
2371 | sctp_association_free(asoc); | 2553 | err = __sctp_connect(sk, addr, af->sockaddr_len); |
2372 | goto out_unlock; | ||
2373 | } | ||
2374 | |||
2375 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
2376 | if (err < 0) { | ||
2377 | sctp_association_free(asoc); | ||
2378 | goto out_unlock; | ||
2379 | } | 2554 | } |
2380 | 2555 | ||
2381 | /* Initialize sk's dport and daddr for getpeername() */ | ||
2382 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
2383 | af = sctp_get_af_specific(to.sa.sa_family); | ||
2384 | af->to_sk_daddr(&to, sk); | ||
2385 | |||
2386 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
2387 | err = sctp_wait_for_connect(asoc, &timeo); | ||
2388 | |||
2389 | out_unlock: | ||
2390 | sctp_release_sock(sk); | 2556 | sctp_release_sock(sk); |
2391 | |||
2392 | return err; | 2557 | return err; |
2393 | } | 2558 | } |
2394 | 2559 | ||
@@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
2677 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 2842 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
2678 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 2843 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), |
2679 | (union sctp_addr *)&status.sstat_primary.spinfo_address); | 2844 | (union sctp_addr *)&status.sstat_primary.spinfo_address); |
2680 | status.sstat_primary.spinfo_state = transport->active; | 2845 | status.sstat_primary.spinfo_state = transport->state; |
2681 | status.sstat_primary.spinfo_cwnd = transport->cwnd; | 2846 | status.sstat_primary.spinfo_cwnd = transport->cwnd; |
2682 | status.sstat_primary.spinfo_srtt = transport->srtt; | 2847 | status.sstat_primary.spinfo_srtt = transport->srtt; |
2683 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); | 2848 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); |
2684 | status.sstat_primary.spinfo_mtu = transport->pmtu; | 2849 | status.sstat_primary.spinfo_mtu = transport->pmtu; |
2685 | 2850 | ||
2851 | if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN) | ||
2852 | status.sstat_primary.spinfo_state = SCTP_ACTIVE; | ||
2853 | |||
2686 | if (put_user(len, optlen)) { | 2854 | if (put_user(len, optlen)) { |
2687 | retval = -EFAULT; | 2855 | retval = -EFAULT; |
2688 | goto out; | 2856 | goto out; |
@@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, | |||
2733 | return -EINVAL; | 2901 | return -EINVAL; |
2734 | 2902 | ||
2735 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); | 2903 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); |
2736 | pinfo.spinfo_state = transport->active; | 2904 | pinfo.spinfo_state = transport->state; |
2737 | pinfo.spinfo_cwnd = transport->cwnd; | 2905 | pinfo.spinfo_cwnd = transport->cwnd; |
2738 | pinfo.spinfo_srtt = transport->srtt; | 2906 | pinfo.spinfo_srtt = transport->srtt; |
2739 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); | 2907 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); |
2740 | pinfo.spinfo_mtu = transport->pmtu; | 2908 | pinfo.spinfo_mtu = transport->pmtu; |
2741 | 2909 | ||
2910 | if (pinfo.spinfo_state == SCTP_UNKNOWN) | ||
2911 | pinfo.spinfo_state = SCTP_ACTIVE; | ||
2912 | |||
2742 | if (put_user(len, optlen)) { | 2913 | if (put_user(len, optlen)) { |
2743 | retval = -EFAULT; | 2914 | retval = -EFAULT; |
2744 | goto out; | 2915 | goto out; |
@@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
3591 | int retval = 0; | 3762 | int retval = 0; |
3592 | int len; | 3763 | int len; |
3593 | 3764 | ||
3594 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk); | 3765 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n", |
3766 | sk, optname); | ||
3595 | 3767 | ||
3596 | /* I can hardly begin to describe how wrong this is. This is | 3768 | /* I can hardly begin to describe how wrong this is. This is |
3597 | * so broken as to be worse than useless. The API draft | 3769 | * so broken as to be worse than useless. The API draft |
@@ -4596,8 +4768,7 @@ out: | |||
4596 | return err; | 4768 | return err; |
4597 | 4769 | ||
4598 | do_error: | 4770 | do_error: |
4599 | if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >= | 4771 | if (asoc->init_err_counter + 1 >= asoc->max_init_attempts) |
4600 | asoc->max_init_attempts) | ||
4601 | err = -ETIMEDOUT; | 4772 | err = -ETIMEDOUT; |
4602 | else | 4773 | else |
4603 | err = -ECONNREFUSED; | 4774 | err = -ECONNREFUSED; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index f30882e1e96a..0ec0fde6e6c5 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -83,7 +83,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
83 | peer->last_time_used = jiffies; | 83 | peer->last_time_used = jiffies; |
84 | peer->last_time_ecne_reduced = jiffies; | 84 | peer->last_time_ecne_reduced = jiffies; |
85 | 85 | ||
86 | peer->active = SCTP_ACTIVE; | 86 | peer->init_sent_count = 0; |
87 | |||
88 | peer->state = SCTP_ACTIVE; | ||
87 | peer->hb_allowed = 0; | 89 | peer->hb_allowed = 0; |
88 | 90 | ||
89 | /* Initialize the default path max_retrans. */ | 91 | /* Initialize the default path max_retrans. */ |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0a4260719a12..d65ed8684fc1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -118,7 +118,6 @@ retry: | |||
118 | xfrm_policy_put_afinfo(afinfo); | 118 | xfrm_policy_put_afinfo(afinfo); |
119 | return type; | 119 | return type; |
120 | } | 120 | } |
121 | EXPORT_SYMBOL(xfrm_get_type); | ||
122 | 121 | ||
123 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, | 122 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, |
124 | unsigned short family) | 123 | unsigned short family) |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 2537f26f097c..9d206c282cf1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1055,6 +1055,43 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | EXPORT_SYMBOL(xfrm_state_mtu); | 1057 | EXPORT_SYMBOL(xfrm_state_mtu); |
1058 | |||
1059 | int xfrm_init_state(struct xfrm_state *x) | ||
1060 | { | ||
1061 | struct xfrm_state_afinfo *afinfo; | ||
1062 | int family = x->props.family; | ||
1063 | int err; | ||
1064 | |||
1065 | err = -EAFNOSUPPORT; | ||
1066 | afinfo = xfrm_state_get_afinfo(family); | ||
1067 | if (!afinfo) | ||
1068 | goto error; | ||
1069 | |||
1070 | err = 0; | ||
1071 | if (afinfo->init_flags) | ||
1072 | err = afinfo->init_flags(x); | ||
1073 | |||
1074 | xfrm_state_put_afinfo(afinfo); | ||
1075 | |||
1076 | if (err) | ||
1077 | goto error; | ||
1078 | |||
1079 | err = -EPROTONOSUPPORT; | ||
1080 | x->type = xfrm_get_type(x->id.proto, family); | ||
1081 | if (x->type == NULL) | ||
1082 | goto error; | ||
1083 | |||
1084 | err = x->type->init_state(x); | ||
1085 | if (err) | ||
1086 | goto error; | ||
1087 | |||
1088 | x->km.state = XFRM_STATE_VALID; | ||
1089 | |||
1090 | error: | ||
1091 | return err; | ||
1092 | } | ||
1093 | |||
1094 | EXPORT_SYMBOL(xfrm_init_state); | ||
1058 | 1095 | ||
1059 | void __init xfrm_state_init(void) | 1096 | void __init xfrm_state_init(void) |
1060 | { | 1097 | { |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 5ce8558eac91..ecade4893a13 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -249,17 +249,10 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | |||
249 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) | 249 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) |
250 | goto error; | 250 | goto error; |
251 | 251 | ||
252 | err = -ENOENT; | 252 | err = xfrm_init_state(x); |
253 | x->type = xfrm_get_type(x->id.proto, x->props.family); | ||
254 | if (x->type == NULL) | ||
255 | goto error; | ||
256 | |||
257 | err = x->type->init_state(x, NULL); | ||
258 | if (err) | 253 | if (err) |
259 | goto error; | 254 | goto error; |
260 | 255 | ||
261 | x->curlft.add_time = (unsigned long) xtime.tv_sec; | ||
262 | x->km.state = XFRM_STATE_VALID; | ||
263 | x->km.seq = p->seq; | 256 | x->km.seq = p->seq; |
264 | 257 | ||
265 | return x; | 258 | return x; |