diff options
103 files changed, 3482 insertions, 2345 deletions
@@ -41,8 +41,9 @@ ifndef KBUILD_VERBOSE | |||
41 | KBUILD_VERBOSE = 0 | 41 | KBUILD_VERBOSE = 0 |
42 | endif | 42 | endif |
43 | 43 | ||
44 | # Call sparse as part of compilation of C files | 44 | # Call checker as part of compilation of C files |
45 | # Use 'make C=1' to enable sparse checking | 45 | # Use 'make C=1' to enable checking (sparse, by default) |
46 | # Override with 'make C=1 CHECK=checker_executable CHECKFLAGS=....' | ||
46 | 47 | ||
47 | ifdef C | 48 | ifdef C |
48 | ifeq ("$(origin C)", "command line") | 49 | ifeq ("$(origin C)", "command line") |
@@ -1060,8 +1061,8 @@ help: | |||
1060 | 1061 | ||
1061 | @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' | 1062 | @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' |
1062 | @echo ' make O=dir [targets] Locate all output files in "dir", including .config' | 1063 | @echo ' make O=dir [targets] Locate all output files in "dir", including .config' |
1063 | @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse)' | 1064 | @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)' |
1064 | @echo ' make C=2 [targets] Force check of all c source with $$CHECK (sparse)' | 1065 | @echo ' make C=2 [targets] Force check of all c source with $$CHECK' |
1065 | @echo '' | 1066 | @echo '' |
1066 | @echo 'Execute "make" or "make all" to build all targets marked with [*] ' | 1067 | @echo 'Execute "make" or "make all" to build all targets marked with [*] ' |
1067 | @echo 'For further info see the ./README file' | 1068 | @echo 'For further info see the ./README file' |
@@ -1352,7 +1353,7 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)) | |||
1352 | 1353 | ||
1353 | a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \ | 1354 | a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \ |
1354 | $(NOSTDINC_FLAGS) $(CPPFLAGS) \ | 1355 | $(NOSTDINC_FLAGS) $(CPPFLAGS) \ |
1355 | $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o) | 1356 | $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o) |
1356 | 1357 | ||
1357 | quiet_cmd_as_o_S = AS $@ | 1358 | quiet_cmd_as_o_S = AS $@ |
1358 | cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< | 1359 | cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< |
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 5e70c2fb273a..cbc1184e9473 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile | |||
@@ -38,6 +38,7 @@ obj-$(CONFIG_VM86) += vm86.o | |||
38 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 38 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
39 | obj-$(CONFIG_HPET_TIMER) += hpet.o | 39 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
40 | obj-$(CONFIG_K8_NB) += k8.o | 40 | obj-$(CONFIG_K8_NB) += k8.o |
41 | obj-$(CONFIG_AUDIT) += audit.o | ||
41 | 42 | ||
42 | EXTRA_AFLAGS := -traditional | 43 | EXTRA_AFLAGS := -traditional |
43 | 44 | ||
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 50eb0e03777e..7b421b3a053e 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c | |||
@@ -168,6 +168,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end) | |||
168 | } | 168 | } |
169 | } | 169 | } |
170 | 170 | ||
171 | #ifdef CONFIG_SMP | ||
172 | |||
171 | static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end) | 173 | static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end) |
172 | { | 174 | { |
173 | struct alt_instr *a; | 175 | struct alt_instr *a; |
@@ -328,6 +330,8 @@ void alternatives_smp_switch(int smp) | |||
328 | spin_unlock_irqrestore(&smp_alt, flags); | 330 | spin_unlock_irqrestore(&smp_alt, flags); |
329 | } | 331 | } |
330 | 332 | ||
333 | #endif | ||
334 | |||
331 | void __init alternative_instructions(void) | 335 | void __init alternative_instructions(void) |
332 | { | 336 | { |
333 | if (no_replacement) { | 337 | if (no_replacement) { |
@@ -349,6 +353,7 @@ void __init alternative_instructions(void) | |||
349 | smp_alt_once = 1; | 353 | smp_alt_once = 1; |
350 | #endif | 354 | #endif |
351 | 355 | ||
356 | #ifdef CONFIG_SMP | ||
352 | if (smp_alt_once) { | 357 | if (smp_alt_once) { |
353 | if (1 == num_possible_cpus()) { | 358 | if (1 == num_possible_cpus()) { |
354 | printk(KERN_INFO "SMP alternatives: switching to UP code\n"); | 359 | printk(KERN_INFO "SMP alternatives: switching to UP code\n"); |
@@ -370,4 +375,5 @@ void __init alternative_instructions(void) | |||
370 | _text, _etext); | 375 | _text, _etext); |
371 | alternatives_smp_switch(0); | 376 | alternatives_smp_switch(0); |
372 | } | 377 | } |
378 | #endif | ||
373 | } | 379 | } |
diff --git a/arch/i386/kernel/audit.c b/arch/i386/kernel/audit.c new file mode 100644 index 000000000000..5a53c6f371ff --- /dev/null +++ b/arch/i386/kernel/audit.c | |||
@@ -0,0 +1,23 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <linux/audit.h> | ||
4 | #include <asm/unistd.h> | ||
5 | |||
6 | static unsigned dir_class[] = { | ||
7 | #include <asm-generic/audit_dir_write.h> | ||
8 | ~0U | ||
9 | }; | ||
10 | |||
11 | static unsigned chattr_class[] = { | ||
12 | #include <asm-generic/audit_change_attr.h> | ||
13 | ~0U | ||
14 | }; | ||
15 | |||
16 | static int __init audit_classes_init(void) | ||
17 | { | ||
18 | audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); | ||
19 | audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | __initcall(audit_classes_init); | ||
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index dc5d8979cd64..89e8486aac34 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -725,16 +725,15 @@ static int noinline do_test_wp_bit(void) | |||
725 | 725 | ||
726 | #ifdef CONFIG_DEBUG_RODATA | 726 | #ifdef CONFIG_DEBUG_RODATA |
727 | 727 | ||
728 | extern char __start_rodata, __end_rodata; | ||
729 | void mark_rodata_ro(void) | 728 | void mark_rodata_ro(void) |
730 | { | 729 | { |
731 | unsigned long addr = (unsigned long)&__start_rodata; | 730 | unsigned long addr = (unsigned long)__start_rodata; |
732 | 731 | ||
733 | for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) | 732 | for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE) |
734 | change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO); | 733 | change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO); |
735 | 734 | ||
736 | printk ("Write protecting the kernel read-only data: %luk\n", | 735 | printk("Write protecting the kernel read-only data: %uk\n", |
737 | (unsigned long)(&__end_rodata - &__start_rodata) >> 10); | 736 | (__end_rodata - __start_rodata) >> 10); |
738 | 737 | ||
739 | /* | 738 | /* |
740 | * change_page_attr() requires a global_flush_tlb() call after it. | 739 | * change_page_attr() requires a global_flush_tlb() call after it. |
diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile index 61cb60affd95..baad8c7699c0 100644 --- a/arch/ia64/ia32/Makefile +++ b/arch/ia64/ia32/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \ | 5 | obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \ |
6 | ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o | 6 | ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o |
7 | obj-$(CONFIG_AUDIT) += audit.o | ||
7 | 8 | ||
8 | # Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and | 9 | # Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and |
9 | # restore_ia32_fpstate_live() can be sure the live register contain user-level state. | 10 | # restore_ia32_fpstate_live() can be sure the live register contain user-level state. |
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c new file mode 100644 index 000000000000..ab94f2e58cdd --- /dev/null +++ b/arch/ia64/ia32/audit.c | |||
@@ -0,0 +1,11 @@ | |||
1 | #include <asm-i386/unistd.h> | ||
2 | |||
3 | unsigned ia32_dir_class[] = { | ||
4 | #include <asm-generic/audit_dir_write.h> | ||
5 | ~0U | ||
6 | }; | ||
7 | |||
8 | unsigned ia32_chattr_class[] = { | ||
9 | #include <asm-generic/audit_change_attr.h> | ||
10 | ~0U | ||
11 | }; | ||
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 09a0dbc17fb6..0e4553f320bf 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile | |||
@@ -29,6 +29,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/ | |||
29 | obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o | 29 | obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o |
30 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o | 30 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o |
31 | obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o | 31 | obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o |
32 | obj-$(CONFIG_AUDIT) += audit.o | ||
32 | mca_recovery-y += mca_drv.o mca_drv_asm.o | 33 | mca_recovery-y += mca_drv.o mca_drv_asm.o |
33 | 34 | ||
34 | # The gate DSO image is built using a special linker script. | 35 | # The gate DSO image is built using a special linker script. |
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c new file mode 100644 index 000000000000..f2512931ccaf --- /dev/null +++ b/arch/ia64/kernel/audit.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <linux/audit.h> | ||
4 | #include <asm/unistd.h> | ||
5 | |||
6 | static unsigned dir_class[] = { | ||
7 | #include <asm-generic/audit_dir_write.h> | ||
8 | ~0U | ||
9 | }; | ||
10 | |||
11 | static unsigned chattr_class[] = { | ||
12 | #include <asm-generic/audit_change_attr.h> | ||
13 | ~0U | ||
14 | }; | ||
15 | |||
16 | static int __init audit_classes_init(void) | ||
17 | { | ||
18 | #ifdef CONFIG_IA32_SUPPORT | ||
19 | extern __u32 ia32_dir_class[]; | ||
20 | extern __u32 ia32_chattr_class[]; | ||
21 | audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); | ||
22 | audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); | ||
23 | #endif | ||
24 | audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); | ||
25 | audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | __initcall(audit_classes_init); | ||
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index b64602a99d89..f2b96f1e0da7 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/tlb.h> | 27 | #include <asm/tlb.h> |
28 | #include <asm/pdc_chassis.h> | 28 | #include <asm/pdc_chassis.h> |
29 | #include <asm/mmzone.h> | 29 | #include <asm/mmzone.h> |
30 | #include <asm/sections.h> | ||
30 | 31 | ||
31 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 32 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
32 | 33 | ||
@@ -417,11 +418,10 @@ void free_initmem(void) | |||
417 | #ifdef CONFIG_DEBUG_RODATA | 418 | #ifdef CONFIG_DEBUG_RODATA |
418 | void mark_rodata_ro(void) | 419 | void mark_rodata_ro(void) |
419 | { | 420 | { |
420 | extern char __start_rodata, __end_rodata; | ||
421 | /* rodata memory was already mapped with KERNEL_RO access rights by | 421 | /* rodata memory was already mapped with KERNEL_RO access rights by |
422 | pagetable_init() and map_pages(). No need to do additional stuff here */ | 422 | pagetable_init() and map_pages(). No need to do additional stuff here */ |
423 | printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n", | 423 | printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n", |
424 | (unsigned long)(&__end_rodata - &__start_rodata) >> 10); | 424 | (unsigned long)(__end_rodata - __start_rodata) >> 10); |
425 | } | 425 | } |
426 | #endif | 426 | #endif |
427 | 427 | ||
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 1a434a7004ee..d8948c342caf 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -228,8 +228,9 @@ sysc_do_svc: | |||
228 | sysc_nr_ok: | 228 | sysc_nr_ok: |
229 | mvc SP_ARGS(4,%r15),SP_R7(%r15) | 229 | mvc SP_ARGS(4,%r15),SP_R7(%r15) |
230 | sysc_do_restart: | 230 | sysc_do_restart: |
231 | l %r8,BASED(.Lsysc_table) | ||
231 | tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) | 232 | tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) |
232 | l %r8,sys_call_table-system_call(%r7,%r13) # get system call addr. | 233 | l %r8,0(%r7,%r8) # get system call addr. |
233 | bnz BASED(sysc_tracesys) | 234 | bnz BASED(sysc_tracesys) |
234 | basr %r14,%r8 # call sys_xxxx | 235 | basr %r14,%r8 # call sys_xxxx |
235 | st %r2,SP_R2(%r15) # store return value (change R2 on stack) | 236 | st %r2,SP_R2(%r15) # store return value (change R2 on stack) |
@@ -330,9 +331,10 @@ sysc_tracesys: | |||
330 | basr %r14,%r1 | 331 | basr %r14,%r1 |
331 | clc SP_R2(4,%r15),BASED(.Lnr_syscalls) | 332 | clc SP_R2(4,%r15),BASED(.Lnr_syscalls) |
332 | bnl BASED(sysc_tracenogo) | 333 | bnl BASED(sysc_tracenogo) |
334 | l %r8,BASED(.Lsysc_table) | ||
333 | l %r7,SP_R2(%r15) # strace might have changed the | 335 | l %r7,SP_R2(%r15) # strace might have changed the |
334 | sll %r7,2 # system call | 336 | sll %r7,2 # system call |
335 | l %r8,sys_call_table-system_call(%r7,%r13) | 337 | l %r8,0(%r7,%r8) |
336 | sysc_tracego: | 338 | sysc_tracego: |
337 | lm %r3,%r6,SP_R3(%r15) | 339 | lm %r3,%r6,SP_R3(%r15) |
338 | l %r2,SP_ORIG_R2(%r15) | 340 | l %r2,SP_ORIG_R2(%r15) |
@@ -1009,6 +1011,7 @@ cleanup_io_leave_insn: | |||
1009 | .Ltrace: .long syscall_trace | 1011 | .Ltrace: .long syscall_trace |
1010 | .Lvfork: .long sys_vfork | 1012 | .Lvfork: .long sys_vfork |
1011 | .Lschedtail: .long schedule_tail | 1013 | .Lschedtail: .long schedule_tail |
1014 | .Lsysc_table: .long sys_call_table | ||
1012 | 1015 | ||
1013 | .Lcritical_start: | 1016 | .Lcritical_start: |
1014 | .long __critical_start + 0x80000000 | 1017 | .long __critical_start + 0x80000000 |
@@ -1017,8 +1020,8 @@ cleanup_io_leave_insn: | |||
1017 | .Lcleanup_critical: | 1020 | .Lcleanup_critical: |
1018 | .long cleanup_critical | 1021 | .long cleanup_critical |
1019 | 1022 | ||
1023 | .section .rodata, "a" | ||
1020 | #define SYSCALL(esa,esame,emu) .long esa | 1024 | #define SYSCALL(esa,esame,emu) .long esa |
1021 | sys_call_table: | 1025 | sys_call_table: |
1022 | #include "syscalls.S" | 1026 | #include "syscalls.S" |
1023 | #undef SYSCALL | 1027 | #undef SYSCALL |
1024 | |||
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index edad60771673..1ca499fa54b4 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -991,6 +991,7 @@ cleanup_io_leave_insn: | |||
991 | .Lcritical_end: | 991 | .Lcritical_end: |
992 | .quad __critical_end | 992 | .quad __critical_end |
993 | 993 | ||
994 | .section .rodata, "a" | ||
994 | #define SYSCALL(esa,esame,emu) .long esame | 995 | #define SYSCALL(esa,esame,emu) .long esame |
995 | sys_call_table: | 996 | sys_call_table: |
996 | #include "syscalls.S" | 997 | #include "syscalls.S" |
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 81dce185f836..eb6ebfef134a 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/pagemap.h> | 24 | #include <linux/pagemap.h> |
25 | #include <linux/bootmem.h> | 25 | #include <linux/bootmem.h> |
26 | #include <linux/pfn.h> | ||
26 | 27 | ||
27 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
28 | #include <asm/system.h> | 29 | #include <asm/system.h> |
@@ -33,6 +34,7 @@ | |||
33 | #include <asm/lowcore.h> | 34 | #include <asm/lowcore.h> |
34 | #include <asm/tlb.h> | 35 | #include <asm/tlb.h> |
35 | #include <asm/tlbflush.h> | 36 | #include <asm/tlbflush.h> |
37 | #include <asm/sections.h> | ||
36 | 38 | ||
37 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 39 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
38 | 40 | ||
@@ -89,17 +91,6 @@ void show_mem(void) | |||
89 | printk("%d pages swap cached\n",cached); | 91 | printk("%d pages swap cached\n",cached); |
90 | } | 92 | } |
91 | 93 | ||
92 | /* References to section boundaries */ | ||
93 | |||
94 | extern unsigned long _text; | ||
95 | extern unsigned long _etext; | ||
96 | extern unsigned long _edata; | ||
97 | extern unsigned long __bss_start; | ||
98 | extern unsigned long _end; | ||
99 | |||
100 | extern unsigned long __init_begin; | ||
101 | extern unsigned long __init_end; | ||
102 | |||
103 | extern unsigned long __initdata zholes_size[]; | 94 | extern unsigned long __initdata zholes_size[]; |
104 | /* | 95 | /* |
105 | * paging_init() sets up the page tables | 96 | * paging_init() sets up the page tables |
@@ -116,6 +107,10 @@ void __init paging_init(void) | |||
116 | unsigned long pfn = 0; | 107 | unsigned long pfn = 0; |
117 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; | 108 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; |
118 | static const int ssm_mask = 0x04000000L; | 109 | static const int ssm_mask = 0x04000000L; |
110 | unsigned long ro_start_pfn, ro_end_pfn; | ||
111 | |||
112 | ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); | ||
113 | ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); | ||
119 | 114 | ||
120 | /* unmap whole virtual address space */ | 115 | /* unmap whole virtual address space */ |
121 | 116 | ||
@@ -143,7 +138,10 @@ void __init paging_init(void) | |||
143 | pg_dir++; | 138 | pg_dir++; |
144 | 139 | ||
145 | for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { | 140 | for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { |
146 | pte = pfn_pte(pfn, PAGE_KERNEL); | 141 | if (pfn >= ro_start_pfn && pfn < ro_end_pfn) |
142 | pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); | ||
143 | else | ||
144 | pte = pfn_pte(pfn, PAGE_KERNEL); | ||
147 | if (pfn >= max_low_pfn) | 145 | if (pfn >= max_low_pfn) |
148 | pte_clear(&init_mm, 0, &pte); | 146 | pte_clear(&init_mm, 0, &pte); |
149 | set_pte(pg_table, pte); | 147 | set_pte(pg_table, pte); |
@@ -175,6 +173,7 @@ void __init paging_init(void) | |||
175 | } | 173 | } |
176 | 174 | ||
177 | #else /* CONFIG_64BIT */ | 175 | #else /* CONFIG_64BIT */ |
176 | |||
178 | void __init paging_init(void) | 177 | void __init paging_init(void) |
179 | { | 178 | { |
180 | pgd_t * pg_dir; | 179 | pgd_t * pg_dir; |
@@ -186,13 +185,15 @@ void __init paging_init(void) | |||
186 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | | 185 | unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | |
187 | _KERN_REGION_TABLE; | 186 | _KERN_REGION_TABLE; |
188 | static const int ssm_mask = 0x04000000L; | 187 | static const int ssm_mask = 0x04000000L; |
189 | |||
190 | unsigned long zones_size[MAX_NR_ZONES]; | 188 | unsigned long zones_size[MAX_NR_ZONES]; |
191 | unsigned long dma_pfn, high_pfn; | 189 | unsigned long dma_pfn, high_pfn; |
190 | unsigned long ro_start_pfn, ro_end_pfn; | ||
192 | 191 | ||
193 | memset(zones_size, 0, sizeof(zones_size)); | 192 | memset(zones_size, 0, sizeof(zones_size)); |
194 | dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; | 193 | dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; |
195 | high_pfn = max_low_pfn; | 194 | high_pfn = max_low_pfn; |
195 | ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); | ||
196 | ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); | ||
196 | 197 | ||
197 | if (dma_pfn > high_pfn) | 198 | if (dma_pfn > high_pfn) |
198 | zones_size[ZONE_DMA] = high_pfn; | 199 | zones_size[ZONE_DMA] = high_pfn; |
@@ -231,7 +232,10 @@ void __init paging_init(void) | |||
231 | pmd_populate_kernel(&init_mm, pm_dir, pt_dir); | 232 | pmd_populate_kernel(&init_mm, pm_dir, pt_dir); |
232 | 233 | ||
233 | for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) { | 234 | for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) { |
234 | pte = pfn_pte(pfn, PAGE_KERNEL); | 235 | if (pfn >= ro_start_pfn && pfn < ro_end_pfn) |
236 | pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); | ||
237 | else | ||
238 | pte = pfn_pte(pfn, PAGE_KERNEL); | ||
235 | if (pfn >= max_low_pfn) { | 239 | if (pfn >= max_low_pfn) { |
236 | pte_clear(&init_mm, 0, &pte); | 240 | pte_clear(&init_mm, 0, &pte); |
237 | continue; | 241 | continue; |
@@ -282,6 +286,9 @@ void __init mem_init(void) | |||
282 | reservedpages << (PAGE_SHIFT-10), | 286 | reservedpages << (PAGE_SHIFT-10), |
283 | datasize >>10, | 287 | datasize >>10, |
284 | initsize >> 10); | 288 | initsize >> 10); |
289 | printk("Write protected kernel read-only data: %#lx - %#lx\n", | ||
290 | (unsigned long)&__start_rodata, | ||
291 | PFN_ALIGN((unsigned long)&__end_rodata) - 1); | ||
285 | } | 292 | } |
286 | 293 | ||
287 | void free_initmem(void) | 294 | void free_initmem(void) |
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 5992c3257167..8912cec0fe43 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "linux/kernel.h" | 8 | #include "linux/kernel.h" |
9 | #include "linux/string.h" | 9 | #include "linux/string.h" |
10 | #include "linux/fs.h" | 10 | #include "linux/fs.h" |
11 | #include "linux/hardirq.h" | ||
11 | #include "linux/highmem.h" | 12 | #include "linux/highmem.h" |
12 | #include "asm/page.h" | 13 | #include "asm/page.h" |
13 | #include "asm/pgtable.h" | 14 | #include "asm/pgtable.h" |
@@ -38,7 +39,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write) | |||
38 | return((unsigned long) phys); | 39 | return((unsigned long) phys); |
39 | } | 40 | } |
40 | 41 | ||
41 | static int do_op(unsigned long addr, int len, int is_write, | 42 | static int do_op_one_page(unsigned long addr, int len, int is_write, |
42 | int (*op)(unsigned long addr, int len, void *arg), void *arg) | 43 | int (*op)(unsigned long addr, int len, void *arg), void *arg) |
43 | { | 44 | { |
44 | struct page *page; | 45 | struct page *page; |
@@ -49,9 +50,11 @@ static int do_op(unsigned long addr, int len, int is_write, | |||
49 | return(-1); | 50 | return(-1); |
50 | 51 | ||
51 | page = phys_to_page(addr); | 52 | page = phys_to_page(addr); |
52 | addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK); | 53 | addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK); |
54 | |||
53 | n = (*op)(addr, len, arg); | 55 | n = (*op)(addr, len, arg); |
54 | kunmap(page); | 56 | |
57 | kunmap_atomic(page, KM_UML_USERCOPY); | ||
55 | 58 | ||
56 | return(n); | 59 | return(n); |
57 | } | 60 | } |
@@ -77,7 +80,7 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) | |||
77 | remain = len; | 80 | remain = len; |
78 | 81 | ||
79 | current->thread.fault_catcher = jmpbuf; | 82 | current->thread.fault_catcher = jmpbuf; |
80 | n = do_op(addr, size, is_write, op, arg); | 83 | n = do_op_one_page(addr, size, is_write, op, arg); |
81 | if(n != 0){ | 84 | if(n != 0){ |
82 | *res = (n < 0 ? remain : 0); | 85 | *res = (n < 0 ? remain : 0); |
83 | goto out; | 86 | goto out; |
@@ -91,7 +94,7 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) | |||
91 | } | 94 | } |
92 | 95 | ||
93 | while(addr < ((addr + remain) & PAGE_MASK)){ | 96 | while(addr < ((addr + remain) & PAGE_MASK)){ |
94 | n = do_op(addr, PAGE_SIZE, is_write, op, arg); | 97 | n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); |
95 | if(n != 0){ | 98 | if(n != 0){ |
96 | *res = (n < 0 ? remain : 0); | 99 | *res = (n < 0 ? remain : 0); |
97 | goto out; | 100 | goto out; |
@@ -105,7 +108,7 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) | |||
105 | goto out; | 108 | goto out; |
106 | } | 109 | } |
107 | 110 | ||
108 | n = do_op(addr, remain, is_write, op, arg); | 111 | n = do_op_one_page(addr, remain, is_write, op, arg); |
109 | if(n != 0) | 112 | if(n != 0) |
110 | *res = (n < 0 ? remain : 0); | 113 | *res = (n < 0 ? remain : 0); |
111 | else *res = 0; | 114 | else *res = 0; |
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index 362db059fe30..48092b95c8ab 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c | |||
@@ -67,32 +67,53 @@ err: | |||
67 | return err; | 67 | return err; |
68 | } | 68 | } |
69 | 69 | ||
70 | static int actually_do_remove(char *dir) | 70 | /* |
71 | * Unlinks the files contained in @dir and then removes @dir. | ||
72 | * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We | ||
73 | * ignore ENOENT errors for anything (they happen, strangely enough - possibly due | ||
74 | * to races between multiple dying UML threads). | ||
75 | */ | ||
76 | static int remove_files_and_dir(char *dir) | ||
71 | { | 77 | { |
72 | DIR *directory; | 78 | DIR *directory; |
73 | struct dirent *ent; | 79 | struct dirent *ent; |
74 | int len; | 80 | int len; |
75 | char file[256]; | 81 | char file[256]; |
82 | int ret; | ||
76 | 83 | ||
77 | directory = opendir(dir); | 84 | directory = opendir(dir); |
78 | if(directory == NULL) | 85 | if (directory == NULL) { |
79 | return -errno; | 86 | if (errno != ENOENT) |
87 | return -errno; | ||
88 | else | ||
89 | return 0; | ||
90 | } | ||
80 | 91 | ||
81 | while((ent = readdir(directory)) != NULL){ | 92 | while ((ent = readdir(directory)) != NULL) { |
82 | if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) | 93 | if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) |
83 | continue; | 94 | continue; |
84 | len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; | 95 | len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; |
85 | if(len > sizeof(file)) | 96 | if (len > sizeof(file)) { |
86 | return -E2BIG; | 97 | ret = -E2BIG; |
98 | goto out; | ||
99 | } | ||
87 | 100 | ||
88 | sprintf(file, "%s/%s", dir, ent->d_name); | 101 | sprintf(file, "%s/%s", dir, ent->d_name); |
89 | if(unlink(file) < 0) | 102 | if (unlink(file) < 0 && errno != ENOENT) { |
90 | return -errno; | 103 | ret = -errno; |
104 | goto out; | ||
105 | } | ||
91 | } | 106 | } |
92 | if(rmdir(dir) < 0) | ||
93 | return -errno; | ||
94 | 107 | ||
95 | return 0; | 108 | if (rmdir(dir) < 0 && errno != ENOENT) { |
109 | ret = -errno; | ||
110 | goto out; | ||
111 | } | ||
112 | |||
113 | ret = 0; | ||
114 | out: | ||
115 | closedir(directory); | ||
116 | return ret; | ||
96 | } | 117 | } |
97 | 118 | ||
98 | /* This says that there isn't already a user of the specified directory even if | 119 | /* This says that there isn't already a user of the specified directory even if |
@@ -103,9 +124,10 @@ static int actually_do_remove(char *dir) | |||
103 | * something other than UML sticking stuff in the directory | 124 | * something other than UML sticking stuff in the directory |
104 | * this boot racing with a shutdown of the other UML | 125 | * this boot racing with a shutdown of the other UML |
105 | * In any of these cases, the directory isn't useful for anything else. | 126 | * In any of these cases, the directory isn't useful for anything else. |
127 | * | ||
128 | * Boolean return: 1 if in use, 0 otherwise. | ||
106 | */ | 129 | */ |
107 | 130 | static inline int is_umdir_used(char *dir) | |
108 | static int not_dead_yet(char *dir) | ||
109 | { | 131 | { |
110 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; | 132 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; |
111 | char pid[sizeof("nnnnn\0")], *end; | 133 | char pid[sizeof("nnnnn\0")], *end; |
@@ -113,7 +135,7 @@ static int not_dead_yet(char *dir) | |||
113 | 135 | ||
114 | n = snprintf(file, sizeof(file), "%s/pid", dir); | 136 | n = snprintf(file, sizeof(file), "%s/pid", dir); |
115 | if(n >= sizeof(file)){ | 137 | if(n >= sizeof(file)){ |
116 | printk("not_dead_yet - pid filename too long\n"); | 138 | printk("is_umdir_used - pid filename too long\n"); |
117 | err = -E2BIG; | 139 | err = -E2BIG; |
118 | goto out; | 140 | goto out; |
119 | } | 141 | } |
@@ -123,7 +145,7 @@ static int not_dead_yet(char *dir) | |||
123 | if(fd < 0) { | 145 | if(fd < 0) { |
124 | fd = -errno; | 146 | fd = -errno; |
125 | if(fd != -ENOENT){ | 147 | if(fd != -ENOENT){ |
126 | printk("not_dead_yet : couldn't open pid file '%s', " | 148 | printk("is_umdir_used : couldn't open pid file '%s', " |
127 | "err = %d\n", file, -fd); | 149 | "err = %d\n", file, -fd); |
128 | } | 150 | } |
129 | goto out; | 151 | goto out; |
@@ -132,18 +154,18 @@ static int not_dead_yet(char *dir) | |||
132 | err = 0; | 154 | err = 0; |
133 | n = read(fd, pid, sizeof(pid)); | 155 | n = read(fd, pid, sizeof(pid)); |
134 | if(n < 0){ | 156 | if(n < 0){ |
135 | printk("not_dead_yet : couldn't read pid file '%s', " | 157 | printk("is_umdir_used : couldn't read pid file '%s', " |
136 | "err = %d\n", file, errno); | 158 | "err = %d\n", file, errno); |
137 | goto out_close; | 159 | goto out_close; |
138 | } else if(n == 0){ | 160 | } else if(n == 0){ |
139 | printk("not_dead_yet : couldn't read pid file '%s', " | 161 | printk("is_umdir_used : couldn't read pid file '%s', " |
140 | "0-byte read\n", file); | 162 | "0-byte read\n", file); |
141 | goto out_close; | 163 | goto out_close; |
142 | } | 164 | } |
143 | 165 | ||
144 | p = strtoul(pid, &end, 0); | 166 | p = strtoul(pid, &end, 0); |
145 | if(end == pid){ | 167 | if(end == pid){ |
146 | printk("not_dead_yet : couldn't parse pid file '%s', " | 168 | printk("is_umdir_used : couldn't parse pid file '%s', " |
147 | "errno = %d\n", file, errno); | 169 | "errno = %d\n", file, errno); |
148 | goto out_close; | 170 | goto out_close; |
149 | } | 171 | } |
@@ -153,19 +175,32 @@ static int not_dead_yet(char *dir) | |||
153 | return 1; | 175 | return 1; |
154 | } | 176 | } |
155 | 177 | ||
156 | err = actually_do_remove(dir); | ||
157 | if(err) | ||
158 | printk("not_dead_yet - actually_do_remove failed with " | ||
159 | "err = %d\n", err); | ||
160 | |||
161 | return err; | ||
162 | |||
163 | out_close: | 178 | out_close: |
164 | close(fd); | 179 | close(fd); |
165 | out: | 180 | out: |
166 | return 0; | 181 | return 0; |
167 | } | 182 | } |
168 | 183 | ||
184 | /* | ||
185 | * Try to remove the directory @dir unless it's in use. | ||
186 | * Precondition: @dir exists. | ||
187 | * Returns 0 for success, < 0 for failure in removal or if the directory is in | ||
188 | * use. | ||
189 | */ | ||
190 | static int umdir_take_if_dead(char *dir) | ||
191 | { | ||
192 | int ret; | ||
193 | if (is_umdir_used(dir)) | ||
194 | return -EEXIST; | ||
195 | |||
196 | ret = remove_files_and_dir(dir); | ||
197 | if (ret) { | ||
198 | printk("is_umdir_used - remove_files_and_dir failed with " | ||
199 | "err = %d\n", ret); | ||
200 | } | ||
201 | return ret; | ||
202 | } | ||
203 | |||
169 | static void __init create_pid_file(void) | 204 | static void __init create_pid_file(void) |
170 | { | 205 | { |
171 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; | 206 | char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; |
@@ -244,11 +279,7 @@ int __init make_umid(void) | |||
244 | if(err != -EEXIST) | 279 | if(err != -EEXIST) |
245 | goto err; | 280 | goto err; |
246 | 281 | ||
247 | /* 1 -> this umid is already in use | 282 | if (umdir_take_if_dead(tmp) < 0) |
248 | * < 0 -> we couldn't remove the umid directory | ||
249 | * In either case, we can't use this umid, so return -EEXIST. | ||
250 | */ | ||
251 | if(not_dead_yet(tmp) != 0) | ||
252 | goto err; | 283 | goto err; |
253 | 284 | ||
254 | err = mkdir(tmp, 0777); | 285 | err = mkdir(tmp, 0777); |
@@ -344,9 +375,9 @@ static void remove_umid_dir(void) | |||
344 | char dir[strlen(uml_dir) + UMID_LEN + 1], err; | 375 | char dir[strlen(uml_dir) + UMID_LEN + 1], err; |
345 | 376 | ||
346 | sprintf(dir, "%s%s", uml_dir, umid); | 377 | sprintf(dir, "%s%s", uml_dir, umid); |
347 | err = actually_do_remove(dir); | 378 | err = remove_files_and_dir(dir); |
348 | if(err) | 379 | if(err) |
349 | printf("remove_umid_dir - actually_do_remove failed with " | 380 | printf("remove_umid_dir - remove_files_and_dir failed with " |
350 | "err = %d\n", err); | 381 | "err = %d\n", err); |
351 | } | 382 | } |
352 | 383 | ||
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index 1347dc6d5218..813077fb1e5b 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules | |||
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) | |||
8 | USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) | 8 | USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) |
9 | 9 | ||
10 | $(USER_OBJS:.o=.%): \ | 10 | $(USER_OBJS:.o=.%): \ |
11 | c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(*F).o) | 11 | c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o) |
12 | $(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ | 12 | $(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ |
13 | -Dunix -D__unix__ -D__$(SUBARCH)__ | 13 | -Dunix -D__unix__ -D__$(SUBARCH)__ |
14 | 14 | ||
@@ -17,7 +17,7 @@ $(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ | |||
17 | UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file)) | 17 | UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file)) |
18 | 18 | ||
19 | $(UNPROFILE_OBJS:.o=.%): \ | 19 | $(UNPROFILE_OBJS:.o=.%): \ |
20 | c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(*F).o) | 20 | c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(basetarget).o) |
21 | $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ | 21 | $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ |
22 | -Dunix -D__unix__ -D__$(SUBARCH)__ | 22 | -Dunix -D__unix__ -D__$(SUBARCH)__ |
23 | 23 | ||
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile index e9263b4975e0..62bc5f56da9e 100644 --- a/arch/x86_64/ia32/Makefile +++ b/arch/x86_64/ia32/Makefile | |||
@@ -11,6 +11,9 @@ obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) | |||
11 | 11 | ||
12 | obj-$(CONFIG_IA32_AOUT) += ia32_aout.o | 12 | obj-$(CONFIG_IA32_AOUT) += ia32_aout.o |
13 | 13 | ||
14 | audit-class-$(CONFIG_AUDIT) := audit.o | ||
15 | obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y) | ||
16 | |||
14 | $(obj)/syscall32_syscall.o: \ | 17 | $(obj)/syscall32_syscall.o: \ |
15 | $(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so) | 18 | $(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so) |
16 | 19 | ||
diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c new file mode 100644 index 000000000000..ab94f2e58cdd --- /dev/null +++ b/arch/x86_64/ia32/audit.c | |||
@@ -0,0 +1,11 @@ | |||
1 | #include <asm-i386/unistd.h> | ||
2 | |||
3 | unsigned ia32_dir_class[] = { | ||
4 | #include <asm-generic/audit_dir_write.h> | ||
5 | ~0U | ||
6 | }; | ||
7 | |||
8 | unsigned ia32_chattr_class[] = { | ||
9 | #include <asm-generic/audit_change_attr.h> | ||
10 | ~0U | ||
11 | }; | ||
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index aeb9c560be88..819e84ec5b64 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile | |||
@@ -35,6 +35,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o | |||
35 | obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o | 35 | obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o |
36 | obj-$(CONFIG_X86_VSMP) += vsmp.o | 36 | obj-$(CONFIG_X86_VSMP) += vsmp.o |
37 | obj-$(CONFIG_K8_NB) += k8.o | 37 | obj-$(CONFIG_K8_NB) += k8.o |
38 | obj-$(CONFIG_AUDIT) += audit.o | ||
38 | 39 | ||
39 | obj-$(CONFIG_MODULES) += module.o | 40 | obj-$(CONFIG_MODULES) += module.o |
40 | 41 | ||
diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c new file mode 100644 index 000000000000..a067aa468a85 --- /dev/null +++ b/arch/x86_64/kernel/audit.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <linux/audit.h> | ||
4 | #include <asm/unistd.h> | ||
5 | |||
6 | static unsigned dir_class[] = { | ||
7 | #include <asm-generic/audit_dir_write.h> | ||
8 | ~0U | ||
9 | }; | ||
10 | |||
11 | static unsigned chattr_class[] = { | ||
12 | #include <asm-generic/audit_change_attr.h> | ||
13 | ~0U | ||
14 | }; | ||
15 | |||
16 | static int __init audit_classes_init(void) | ||
17 | { | ||
18 | #ifdef CONFIG_IA32_EMULATION | ||
19 | extern __u32 ia32_dir_class[]; | ||
20 | extern __u32 ia32_chattr_class[]; | ||
21 | audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); | ||
22 | audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); | ||
23 | #endif | ||
24 | audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); | ||
25 | audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | __initcall(audit_classes_init); | ||
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 72f140f81b70..d14fb2dfbfc4 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
@@ -678,16 +678,15 @@ void free_initmem(void) | |||
678 | 678 | ||
679 | #ifdef CONFIG_DEBUG_RODATA | 679 | #ifdef CONFIG_DEBUG_RODATA |
680 | 680 | ||
681 | extern char __start_rodata, __end_rodata; | ||
682 | void mark_rodata_ro(void) | 681 | void mark_rodata_ro(void) |
683 | { | 682 | { |
684 | unsigned long addr = (unsigned long)&__start_rodata; | 683 | unsigned long addr = (unsigned long)__start_rodata; |
685 | 684 | ||
686 | for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) | 685 | for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE) |
687 | change_page_attr_addr(addr, 1, PAGE_KERNEL_RO); | 686 | change_page_attr_addr(addr, 1, PAGE_KERNEL_RO); |
688 | 687 | ||
689 | printk ("Write protecting the kernel read-only data: %luk\n", | 688 | printk ("Write protecting the kernel read-only data: %luk\n", |
690 | (&__end_rodata - &__start_rodata) >> 10); | 689 | (__end_rodata - __start_rodata) >> 10); |
691 | 690 | ||
692 | /* | 691 | /* |
693 | * change_page_attr_addr() requires a global_flush_tlb() call after it. | 692 | * change_page_attr_addr() requires a global_flush_tlb() call after it. |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index dec044c04273..ea5a0496a4fd 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -192,7 +192,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) | |||
192 | /* Make sure this is a valid target state */ | 192 | /* Make sure this is a valid target state */ |
193 | 193 | ||
194 | if (!device->flags.power_manageable) { | 194 | if (!device->flags.power_manageable) { |
195 | printk(KERN_DEBUG "Device `[%s]is not power manageable", | 195 | printk(KERN_DEBUG "Device `[%s]' is not power manageable", |
196 | device->kobj.name); | 196 | device->kobj.name); |
197 | return -ENODEV; | 197 | return -ENODEV; |
198 | } | 198 | } |
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 39662f0c9cce..0a1b1ea36ddc 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -50,9 +50,9 @@ | |||
50 | #define DBG_RX 0x0200 | 50 | #define DBG_RX 0x0200 |
51 | #define DBG_TX 0x0400 | 51 | #define DBG_TX 0x0400 |
52 | static unsigned int debugflags; | 52 | static unsigned int debugflags; |
53 | static unsigned int nbds_max = 16; | ||
54 | #endif /* NDEBUG */ | 53 | #endif /* NDEBUG */ |
55 | 54 | ||
55 | static unsigned int nbds_max = 16; | ||
56 | static struct nbd_device nbd_dev[MAX_NBD]; | 56 | static struct nbd_device nbd_dev[MAX_NBD]; |
57 | 57 | ||
58 | /* | 58 | /* |
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index d75864e35fef..f79f6b587bfa 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include "edac_mc.h" | 20 | #include "edac_mc.h" |
21 | 21 | ||
22 | #define AMD76X_REVISION " Ver: 2.0.0 " __DATE__ | 22 | #define AMD76X_REVISION " Ver: 2.0.1 " __DATE__ |
23 | 23 | #define EDAC_MOD_STR "amd76x_edac" | |
24 | 24 | ||
25 | #define amd76x_printk(level, fmt, arg...) \ | 25 | #define amd76x_printk(level, fmt, arg...) \ |
26 | edac_printk(level, "amd76x", fmt, ##arg) | 26 | edac_printk(level, "amd76x", fmt, ##arg) |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 815c3eb783de..c82bc0ed7f14 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -24,7 +24,8 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include "edac_mc.h" | 25 | #include "edac_mc.h" |
26 | 26 | ||
27 | #define E752X_REVISION " Ver: 2.0.0 " __DATE__ | 27 | #define E752X_REVISION " Ver: 2.0.1 " __DATE__ |
28 | #define EDAC_MOD_STR "e752x_edac" | ||
28 | 29 | ||
29 | static int force_function_unhide; | 30 | static int force_function_unhide; |
30 | 31 | ||
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 5a5ecd5a0409..310d91b41c96 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c | |||
@@ -29,7 +29,8 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include "edac_mc.h" | 30 | #include "edac_mc.h" |
31 | 31 | ||
32 | #define E7XXX_REVISION " Ver: 2.0.0 " __DATE__ | 32 | #define E7XXX_REVISION " Ver: 2.0.1 " __DATE__ |
33 | #define EDAC_MOD_STR "e7xxx_edac" | ||
33 | 34 | ||
34 | #define e7xxx_printk(level, fmt, arg...) \ | 35 | #define e7xxx_printk(level, fmt, arg...) \ |
35 | edac_printk(level, "e7xxx", fmt, ##arg) | 36 | edac_printk(level, "e7xxx", fmt, ##arg) |
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index 1be4947e28af..bf6ab8a8d5ed 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h | |||
@@ -78,10 +78,6 @@ extern int edac_debug_level; | |||
78 | 78 | ||
79 | #endif /* !CONFIG_EDAC_DEBUG */ | 79 | #endif /* !CONFIG_EDAC_DEBUG */ |
80 | 80 | ||
81 | #define edac_xstr(s) edac_str(s) | ||
82 | #define edac_str(s) #s | ||
83 | #define EDAC_MOD_STR edac_xstr(KBUILD_BASENAME) | ||
84 | |||
85 | #define BIT(x) (1 << (x)) | 81 | #define BIT(x) (1 << (x)) |
86 | 82 | ||
87 | #define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ | 83 | #define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ |
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index e30a4a2eaf38..e4bb298e613f 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c | |||
@@ -16,7 +16,8 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include "edac_mc.h" | 17 | #include "edac_mc.h" |
18 | 18 | ||
19 | #define I82860_REVISION " Ver: 2.0.0 " __DATE__ | 19 | #define I82860_REVISION " Ver: 2.0.1 " __DATE__ |
20 | #define EDAC_MOD_STR "i82860_edac" | ||
20 | 21 | ||
21 | #define i82860_printk(level, fmt, arg...) \ | 22 | #define i82860_printk(level, fmt, arg...) \ |
22 | edac_printk(level, "i82860", fmt, ##arg) | 23 | edac_printk(level, "i82860", fmt, ##arg) |
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 9423ee5e7edd..161fe09a6d38 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include "edac_mc.h" | 21 | #include "edac_mc.h" |
22 | 22 | ||
23 | #define I82875P_REVISION " Ver: 2.0.0 " __DATE__ | 23 | #define I82875P_REVISION " Ver: 2.0.1 " __DATE__ |
24 | #define EDAC_MOD_STR "i82875p_edac" | ||
24 | 25 | ||
25 | #define i82875p_printk(level, fmt, arg...) \ | 26 | #define i82875p_printk(level, fmt, arg...) \ |
26 | edac_printk(level, "i82875p", fmt, ##arg) | 27 | edac_printk(level, "i82875p", fmt, ##arg) |
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index a0e248d11ed9..a49cf0a39398 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c | |||
@@ -22,7 +22,8 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include "edac_mc.h" | 23 | #include "edac_mc.h" |
24 | 24 | ||
25 | #define R82600_REVISION " Ver: 2.0.0 " __DATE__ | 25 | #define R82600_REVISION " Ver: 2.0.1 " __DATE__ |
26 | #define EDAC_MOD_STR "r82600_edac" | ||
26 | 27 | ||
27 | #define r82600_printk(level, fmt, arg...) \ | 28 | #define r82600_printk(level, fmt, arg...) \ |
28 | edac_printk(level, "r82600", fmt, ##arg) | 29 | edac_printk(level, "r82600", fmt, ##arg) |
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 7fb3635683dc..3cb04424d351 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c | |||
@@ -650,6 +650,8 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) | |||
650 | } | 650 | } |
651 | ide_set_hwifdata(hwif, idev); | 651 | ide_set_hwifdata(hwif, idev); |
652 | 652 | ||
653 | hwif->atapi_dma = 1; | ||
654 | |||
653 | pci_read_config_byte(hwif->pci_dev, 0x50, &conf); | 655 | pci_read_config_byte(hwif->pci_dev, 0x50, &conf); |
654 | if(conf & 1) { | 656 | if(conf & 1) { |
655 | idev->smart = 1; | 657 | idev->smart = 1; |
diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig index 9ea67c409b6d..1db9489f1e82 100644 --- a/drivers/infiniband/hw/ipath/Kconfig +++ b/drivers/infiniband/hw/ipath/Kconfig | |||
@@ -1,16 +1,16 @@ | |||
1 | config IPATH_CORE | 1 | config IPATH_CORE |
2 | tristate "PathScale InfiniPath Driver" | 2 | tristate "QLogic InfiniPath Driver" |
3 | depends on 64BIT && PCI_MSI && NET | 3 | depends on 64BIT && PCI_MSI && NET |
4 | ---help--- | 4 | ---help--- |
5 | This is a low-level driver for PathScale InfiniPath host channel | 5 | This is a low-level driver for QLogic InfiniPath host channel |
6 | adapters (HCAs) based on the HT-400 and PE-800 chips. | 6 | adapters (HCAs) based on the HT-400 and PE-800 chips. |
7 | 7 | ||
8 | config INFINIBAND_IPATH | 8 | config INFINIBAND_IPATH |
9 | tristate "PathScale InfiniPath Verbs Driver" | 9 | tristate "QLogic InfiniPath Verbs Driver" |
10 | depends on IPATH_CORE && INFINIBAND | 10 | depends on IPATH_CORE && INFINIBAND |
11 | ---help--- | 11 | ---help--- |
12 | This is a driver that provides InfiniBand verbs support for | 12 | This is a driver that provides InfiniBand verbs support for |
13 | PathScale InfiniPath host channel adapters (HCAs). This | 13 | QLogic InfiniPath host channel adapters (HCAs). This |
14 | allows these devices to be used with both kernel upper level | 14 | allows these devices to be used with both kernel upper level |
15 | protocols such as IP-over-InfiniBand as well as with userspace | 15 | protocols such as IP-over-InfiniBand as well as with userspace |
16 | applications (in conjunction with InfiniBand userspace access). | 16 | applications (in conjunction with InfiniBand userspace access). |
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile index b4d084abfd22..b0bf72864130 100644 --- a/drivers/infiniband/hw/ipath/Makefile +++ b/drivers/infiniband/hw/ipath/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | EXTRA_CFLAGS += -DIPATH_IDSTR='"PathScale kernel.org driver"' \ | 1 | EXTRA_CFLAGS += -DIPATH_IDSTR='"QLogic kernel.org driver"' \ |
2 | -DIPATH_KERN_TYPE=0 | 2 | -DIPATH_KERN_TYPE=0 |
3 | 3 | ||
4 | obj-$(CONFIG_IPATH_CORE) += ipath_core.o | 4 | obj-$(CONFIG_IPATH_CORE) += ipath_core.o |
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h index 48a55247b832..062bd392e7e5 100644 --- a/drivers/infiniband/hw/ipath/ipath_common.h +++ b/drivers/infiniband/hw/ipath/ipath_common.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -38,7 +39,8 @@ | |||
38 | * to communicate between kernel and user code. | 39 | * to communicate between kernel and user code. |
39 | */ | 40 | */ |
40 | 41 | ||
41 | /* This is the IEEE-assigned OUI for PathScale, Inc. */ | 42 | |
43 | /* This is the IEEE-assigned OUI for QLogic Inc. InfiniPath */ | ||
42 | #define IPATH_SRC_OUI_1 0x00 | 44 | #define IPATH_SRC_OUI_1 0x00 |
43 | #define IPATH_SRC_OUI_2 0x11 | 45 | #define IPATH_SRC_OUI_2 0x11 |
44 | #define IPATH_SRC_OUI_3 0x75 | 46 | #define IPATH_SRC_OUI_3 0x75 |
@@ -96,8 +98,8 @@ struct infinipath_stats { | |||
96 | __u64 sps_hwerrs; | 98 | __u64 sps_hwerrs; |
97 | /* number of times IB link changed state unexpectedly */ | 99 | /* number of times IB link changed state unexpectedly */ |
98 | __u64 sps_iblink; | 100 | __u64 sps_iblink; |
99 | /* no longer used; left for compatibility */ | 101 | /* kernel receive interrupts that didn't read intstat */ |
100 | __u64 sps_unused3; | 102 | __u64 sps_fastrcvint; |
101 | /* number of kernel (port0) packets received */ | 103 | /* number of kernel (port0) packets received */ |
102 | __u64 sps_port0pkts; | 104 | __u64 sps_port0pkts; |
103 | /* number of "ethernet" packets sent by driver */ | 105 | /* number of "ethernet" packets sent by driver */ |
@@ -121,8 +123,7 @@ struct infinipath_stats { | |||
121 | __u64 sps_ports; | 123 | __u64 sps_ports; |
122 | /* list of pkeys (other than default) accepted (0 means not set) */ | 124 | /* list of pkeys (other than default) accepted (0 means not set) */ |
123 | __u16 sps_pkeys[4]; | 125 | __u16 sps_pkeys[4]; |
124 | /* lids for up to 4 infinipaths, indexed by infinipath # */ | 126 | __u16 sps_unused16[4]; /* available; maintaining compatible layout */ |
125 | __u16 sps_lid[4]; | ||
126 | /* number of user ports per chip (not IB ports) */ | 127 | /* number of user ports per chip (not IB ports) */ |
127 | __u32 sps_nports; | 128 | __u32 sps_nports; |
128 | /* not our interrupt, or already handled */ | 129 | /* not our interrupt, or already handled */ |
@@ -140,10 +141,8 @@ struct infinipath_stats { | |||
140 | * packets if ipath not configured, sma/mad, etc.) | 141 | * packets if ipath not configured, sma/mad, etc.) |
141 | */ | 142 | */ |
142 | __u64 sps_krdrops; | 143 | __u64 sps_krdrops; |
143 | /* mlids for up to 4 infinipaths, indexed by infinipath # */ | ||
144 | __u16 sps_mlid[4]; | ||
145 | /* pad for future growth */ | 144 | /* pad for future growth */ |
146 | __u64 __sps_pad[45]; | 145 | __u64 __sps_pad[46]; |
147 | }; | 146 | }; |
148 | 147 | ||
149 | /* | 148 | /* |
@@ -310,6 +309,9 @@ struct ipath_base_info { | |||
310 | __u32 spi_rcv_egrchunksize; | 309 | __u32 spi_rcv_egrchunksize; |
311 | /* total size of mmap to cover full rcvegrbuffers */ | 310 | /* total size of mmap to cover full rcvegrbuffers */ |
312 | __u32 spi_rcv_egrbuftotlen; | 311 | __u32 spi_rcv_egrbuftotlen; |
312 | __u32 spi_filler_for_align; | ||
313 | /* address of readonly memory copy of the rcvhdrq tail register. */ | ||
314 | __u64 spi_rcvhdr_tailaddr; | ||
313 | } __attribute__ ((aligned(8))); | 315 | } __attribute__ ((aligned(8))); |
314 | 316 | ||
315 | 317 | ||
@@ -342,9 +344,9 @@ struct ipath_base_info { | |||
342 | /* | 344 | /* |
343 | * Similarly, this is the kernel version going back to the user. It's | 345 | * Similarly, this is the kernel version going back to the user. It's |
344 | * slightly different, in that we want to tell if the driver was built as | 346 | * slightly different, in that we want to tell if the driver was built as |
345 | * part of a PathScale release, or from the driver from OpenIB, kernel.org, | 347 | * part of a QLogic release, or from the driver from openfabrics.org, |
346 | * or a standard distribution, for support reasons. The high bit is 0 for | 348 | * kernel.org, or a standard distribution, for support reasons. |
347 | * non-PathScale, and 1 for PathScale-built/supplied. | 349 | * The high bit is 0 for non-QLogic and 1 for QLogic-built/supplied. |
348 | * | 350 | * |
349 | * It's returned by the driver to the user code during initialization in the | 351 | * It's returned by the driver to the user code during initialization in the |
350 | * spi_sw_version field of ipath_base_info, so the user code can in turn | 352 | * spi_sw_version field of ipath_base_info, so the user code can in turn |
@@ -379,13 +381,7 @@ struct ipath_user_info { | |||
379 | */ | 381 | */ |
380 | __u32 spu_rcvhdrsize; | 382 | __u32 spu_rcvhdrsize; |
381 | 383 | ||
382 | /* | 384 | __u64 spu_unused; /* kept for compatible layout */ |
383 | * cache line aligned (64 byte) user address to | ||
384 | * which the rcvhdrtail register will be written by infinipath | ||
385 | * whenever it changes, so that no chip registers are read in | ||
386 | * the performance path. | ||
387 | */ | ||
388 | __u64 spu_rcvhdraddr; | ||
389 | 385 | ||
390 | /* | 386 | /* |
391 | * address of struct base_info to write to | 387 | * address of struct base_info to write to |
@@ -481,7 +477,7 @@ struct ipath_sma_pkt | |||
481 | * Data layout in I2C flash (for GUID, etc.) | 477 | * Data layout in I2C flash (for GUID, etc.) |
482 | * All fields are little-endian binary unless otherwise stated | 478 | * All fields are little-endian binary unless otherwise stated |
483 | */ | 479 | */ |
484 | #define IPATH_FLASH_VERSION 1 | 480 | #define IPATH_FLASH_VERSION 2 |
485 | struct ipath_flash { | 481 | struct ipath_flash { |
486 | /* flash layout version (IPATH_FLASH_VERSION) */ | 482 | /* flash layout version (IPATH_FLASH_VERSION) */ |
487 | __u8 if_fversion; | 483 | __u8 if_fversion; |
@@ -489,14 +485,14 @@ struct ipath_flash { | |||
489 | __u8 if_csum; | 485 | __u8 if_csum; |
490 | /* | 486 | /* |
491 | * valid length (in use, protected by if_csum), including | 487 | * valid length (in use, protected by if_csum), including |
492 | * if_fversion and if_sum themselves) | 488 | * if_fversion and if_csum themselves) |
493 | */ | 489 | */ |
494 | __u8 if_length; | 490 | __u8 if_length; |
495 | /* the GUID, in network order */ | 491 | /* the GUID, in network order */ |
496 | __u8 if_guid[8]; | 492 | __u8 if_guid[8]; |
497 | /* number of GUIDs to use, starting from if_guid */ | 493 | /* number of GUIDs to use, starting from if_guid */ |
498 | __u8 if_numguid; | 494 | __u8 if_numguid; |
499 | /* the board serial number, in ASCII */ | 495 | /* the (last 10 characters of) board serial number, in ASCII */ |
500 | char if_serial[12]; | 496 | char if_serial[12]; |
501 | /* board mfg date (YYYYMMDD ASCII) */ | 497 | /* board mfg date (YYYYMMDD ASCII) */ |
502 | char if_mfgdate[8]; | 498 | char if_mfgdate[8]; |
@@ -508,8 +504,10 @@ struct ipath_flash { | |||
508 | __u8 if_powerhour[2]; | 504 | __u8 if_powerhour[2]; |
509 | /* ASCII free-form comment field */ | 505 | /* ASCII free-form comment field */ |
510 | char if_comment[32]; | 506 | char if_comment[32]; |
511 | /* 78 bytes used, min flash size is 128 bytes */ | 507 | /* Backwards compatible prefix for longer QLogic Serial Numbers */ |
512 | __u8 if_future[50]; | 508 | char if_sprefix[4]; |
509 | /* 82 bytes used, min flash size is 128 bytes */ | ||
510 | __u8 if_future[46]; | ||
513 | }; | 511 | }; |
514 | 512 | ||
515 | /* | 513 | /* |
@@ -603,14 +601,118 @@ struct infinipath_counters { | |||
603 | #define INFINIPATH_KPF_INTR 0x1 | 601 | #define INFINIPATH_KPF_INTR 0x1 |
604 | 602 | ||
605 | /* SendPIO per-buffer control */ | 603 | /* SendPIO per-buffer control */ |
606 | #define INFINIPATH_SP_LENGTHP1_MASK 0x3FF | 604 | #define INFINIPATH_SP_TEST 0x40 |
607 | #define INFINIPATH_SP_LENGTHP1_SHIFT 0 | 605 | #define INFINIPATH_SP_TESTEBP 0x20 |
608 | #define INFINIPATH_SP_INTR 0x80000000 | ||
609 | #define INFINIPATH_SP_TEST 0x40000000 | ||
610 | #define INFINIPATH_SP_TESTEBP 0x20000000 | ||
611 | 606 | ||
612 | /* SendPIOAvail bits */ | 607 | /* SendPIOAvail bits */ |
613 | #define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1 | 608 | #define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1 |
614 | #define INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT 0 | 609 | #define INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT 0 |
615 | 610 | ||
611 | /* infinipath header format */ | ||
612 | struct ipath_header { | ||
613 | /* | ||
614 | * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset - | ||
615 | * 14 bits before ECO change ~28 Dec 03. After that, Vers 4, | ||
616 | * Port 3, TID 11, offset 14. | ||
617 | */ | ||
618 | __le32 ver_port_tid_offset; | ||
619 | __le16 chksum; | ||
620 | __le16 pkt_flags; | ||
621 | }; | ||
622 | |||
623 | /* infinipath user message header format. | ||
624 | * This structure contains the first 4 fields common to all protocols | ||
625 | * that employ infinipath. | ||
626 | */ | ||
627 | struct ipath_message_header { | ||
628 | __be16 lrh[4]; | ||
629 | __be32 bth[3]; | ||
630 | /* fields below this point are in host byte order */ | ||
631 | struct ipath_header iph; | ||
632 | __u8 sub_opcode; | ||
633 | }; | ||
634 | |||
635 | /* infinipath ethernet header format */ | ||
636 | struct ether_header { | ||
637 | __be16 lrh[4]; | ||
638 | __be32 bth[3]; | ||
639 | struct ipath_header iph; | ||
640 | __u8 sub_opcode; | ||
641 | __u8 cmd; | ||
642 | __be16 lid; | ||
643 | __u16 mac[3]; | ||
644 | __u8 frag_num; | ||
645 | __u8 seq_num; | ||
646 | __le32 len; | ||
647 | /* MUST be of word size due to PIO write requirements */ | ||
648 | __le32 csum; | ||
649 | __le16 csum_offset; | ||
650 | __le16 flags; | ||
651 | __u16 first_2_bytes; | ||
652 | __u8 unused[2]; /* currently unused */ | ||
653 | }; | ||
654 | |||
655 | |||
656 | /* IB - LRH header consts */ | ||
657 | #define IPATH_LRH_GRH 0x0003 /* 1. word of IB LRH - next header: GRH */ | ||
658 | #define IPATH_LRH_BTH 0x0002 /* 1. word of IB LRH - next header: BTH */ | ||
659 | |||
660 | /* misc. */ | ||
661 | #define SIZE_OF_CRC 1 | ||
662 | |||
663 | #define IPATH_DEFAULT_P_KEY 0xFFFF | ||
664 | #define IPATH_PERMISSIVE_LID 0xFFFF | ||
665 | #define IPATH_AETH_CREDIT_SHIFT 24 | ||
666 | #define IPATH_AETH_CREDIT_MASK 0x1F | ||
667 | #define IPATH_AETH_CREDIT_INVAL 0x1F | ||
668 | #define IPATH_PSN_MASK 0xFFFFFF | ||
669 | #define IPATH_MSN_MASK 0xFFFFFF | ||
670 | #define IPATH_QPN_MASK 0xFFFFFF | ||
671 | #define IPATH_MULTICAST_LID_BASE 0xC000 | ||
672 | #define IPATH_MULTICAST_QPN 0xFFFFFF | ||
673 | |||
674 | /* Receive Header Queue: receive type (from infinipath) */ | ||
675 | #define RCVHQ_RCV_TYPE_EXPECTED 0 | ||
676 | #define RCVHQ_RCV_TYPE_EAGER 1 | ||
677 | #define RCVHQ_RCV_TYPE_NON_KD 2 | ||
678 | #define RCVHQ_RCV_TYPE_ERROR 3 | ||
679 | |||
680 | |||
681 | /* sub OpCodes - ith4x */ | ||
682 | #define IPATH_ITH4X_OPCODE_ENCAP 0x81 | ||
683 | #define IPATH_ITH4X_OPCODE_LID_ARP 0x82 | ||
684 | |||
685 | #define IPATH_HEADER_QUEUE_WORDS 9 | ||
686 | |||
687 | /* functions for extracting fields from rcvhdrq entries for the driver. | ||
688 | */ | ||
689 | static inline __u32 ipath_hdrget_err_flags(const __le32 * rbuf) | ||
690 | { | ||
691 | return __le32_to_cpu(rbuf[1]); | ||
692 | } | ||
693 | |||
694 | static inline __u32 ipath_hdrget_rcv_type(const __le32 * rbuf) | ||
695 | { | ||
696 | return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_RCVTYPE_SHIFT) | ||
697 | & INFINIPATH_RHF_RCVTYPE_MASK; | ||
698 | } | ||
699 | |||
700 | static inline __u32 ipath_hdrget_length_in_bytes(const __le32 * rbuf) | ||
701 | { | ||
702 | return ((__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_LENGTH_SHIFT) | ||
703 | & INFINIPATH_RHF_LENGTH_MASK) << 2; | ||
704 | } | ||
705 | |||
706 | static inline __u32 ipath_hdrget_index(const __le32 * rbuf) | ||
707 | { | ||
708 | return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_EGRINDEX_SHIFT) | ||
709 | & INFINIPATH_RHF_EGRINDEX_MASK; | ||
710 | } | ||
711 | |||
712 | static inline __u32 ipath_hdrget_ipath_ver(__le32 hdrword) | ||
713 | { | ||
714 | return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT) | ||
715 | & INFINIPATH_I_VERS_MASK; | ||
716 | } | ||
717 | |||
616 | #endif /* _IPATH_COMMON_H */ | 718 | #endif /* _IPATH_COMMON_H */ |
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c index 7ece1135ddfe..3efee341c9bc 100644 --- a/drivers/infiniband/hw/ipath/ipath_cq.c +++ b/drivers/infiniband/hw/ipath/ipath_cq.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -157,10 +158,21 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, | |||
157 | struct ib_ucontext *context, | 158 | struct ib_ucontext *context, |
158 | struct ib_udata *udata) | 159 | struct ib_udata *udata) |
159 | { | 160 | { |
161 | struct ipath_ibdev *dev = to_idev(ibdev); | ||
160 | struct ipath_cq *cq; | 162 | struct ipath_cq *cq; |
161 | struct ib_wc *wc; | 163 | struct ib_wc *wc; |
162 | struct ib_cq *ret; | 164 | struct ib_cq *ret; |
163 | 165 | ||
166 | if (entries > ib_ipath_max_cqes) { | ||
167 | ret = ERR_PTR(-EINVAL); | ||
168 | goto bail; | ||
169 | } | ||
170 | |||
171 | if (dev->n_cqs_allocated == ib_ipath_max_cqs) { | ||
172 | ret = ERR_PTR(-ENOMEM); | ||
173 | goto bail; | ||
174 | } | ||
175 | |||
164 | /* | 176 | /* |
165 | * Need to use vmalloc() if we want to support large #s of | 177 | * Need to use vmalloc() if we want to support large #s of |
166 | * entries. | 178 | * entries. |
@@ -196,6 +208,8 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, | |||
196 | 208 | ||
197 | ret = &cq->ibcq; | 209 | ret = &cq->ibcq; |
198 | 210 | ||
211 | dev->n_cqs_allocated++; | ||
212 | |||
199 | bail: | 213 | bail: |
200 | return ret; | 214 | return ret; |
201 | } | 215 | } |
@@ -210,9 +224,11 @@ bail: | |||
210 | */ | 224 | */ |
211 | int ipath_destroy_cq(struct ib_cq *ibcq) | 225 | int ipath_destroy_cq(struct ib_cq *ibcq) |
212 | { | 226 | { |
227 | struct ipath_ibdev *dev = to_idev(ibcq->device); | ||
213 | struct ipath_cq *cq = to_icq(ibcq); | 228 | struct ipath_cq *cq = to_icq(ibcq); |
214 | 229 | ||
215 | tasklet_kill(&cq->comptask); | 230 | tasklet_kill(&cq->comptask); |
231 | dev->n_cqs_allocated--; | ||
216 | vfree(cq->queue); | 232 | vfree(cq->queue); |
217 | kfree(cq); | 233 | kfree(cq); |
218 | 234 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h index 46762387f5f8..f415beda0d32 100644 --- a/drivers/infiniband/hw/ipath/ipath_debug.h +++ b/drivers/infiniband/hw/ipath/ipath_debug.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c index 28ddceb260e8..147dd89e21c9 100644 --- a/drivers/infiniband/hw/ipath/ipath_diag.c +++ b/drivers/infiniband/hw/ipath/ipath_diag.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -43,10 +44,9 @@ | |||
43 | #include <linux/pci.h> | 44 | #include <linux/pci.h> |
44 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
45 | 46 | ||
46 | #include "ipath_common.h" | ||
47 | #include "ipath_kernel.h" | 47 | #include "ipath_kernel.h" |
48 | #include "ips_common.h" | ||
49 | #include "ipath_layer.h" | 48 | #include "ipath_layer.h" |
49 | #include "ipath_common.h" | ||
50 | 50 | ||
51 | int ipath_diag_inuse; | 51 | int ipath_diag_inuse; |
52 | static int diag_set_link; | 52 | static int diag_set_link; |
@@ -66,18 +66,20 @@ static struct file_operations diag_file_ops = { | |||
66 | .release = ipath_diag_release | 66 | .release = ipath_diag_release |
67 | }; | 67 | }; |
68 | 68 | ||
69 | static struct cdev *diag_cdev; | 69 | int ipath_diag_add(struct ipath_devdata *dd) |
70 | static struct class_device *diag_class_dev; | ||
71 | |||
72 | int ipath_diag_init(void) | ||
73 | { | 70 | { |
74 | return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag", | 71 | char name[16]; |
75 | &diag_file_ops, &diag_cdev, &diag_class_dev); | 72 | |
73 | snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit); | ||
74 | |||
75 | return ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name, | ||
76 | &diag_file_ops, &dd->diag_cdev, | ||
77 | &dd->diag_class_dev); | ||
76 | } | 78 | } |
77 | 79 | ||
78 | void ipath_diag_cleanup(void) | 80 | void ipath_diag_remove(struct ipath_devdata *dd) |
79 | { | 81 | { |
80 | ipath_cdev_cleanup(&diag_cdev, &diag_class_dev); | 82 | ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev); |
81 | } | 83 | } |
82 | 84 | ||
83 | /** | 85 | /** |
@@ -101,8 +103,7 @@ static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr, | |||
101 | int ret; | 103 | int ret; |
102 | 104 | ||
103 | /* not very efficient, but it works for now */ | 105 | /* not very efficient, but it works for now */ |
104 | if (reg_addr < dd->ipath_kregbase || | 106 | if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) { |
105 | reg_end > dd->ipath_kregend) { | ||
106 | ret = -EINVAL; | 107 | ret = -EINVAL; |
107 | goto bail; | 108 | goto bail; |
108 | } | 109 | } |
@@ -113,7 +114,7 @@ static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr, | |||
113 | goto bail; | 114 | goto bail; |
114 | } | 115 | } |
115 | reg_addr++; | 116 | reg_addr++; |
116 | uaddr++; | 117 | uaddr += sizeof(u64); |
117 | } | 118 | } |
118 | ret = 0; | 119 | ret = 0; |
119 | bail: | 120 | bail: |
@@ -139,8 +140,7 @@ static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr, | |||
139 | int ret; | 140 | int ret; |
140 | 141 | ||
141 | /* not very efficient, but it works for now */ | 142 | /* not very efficient, but it works for now */ |
142 | if (reg_addr < dd->ipath_kregbase || | 143 | if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) { |
143 | reg_end > dd->ipath_kregend) { | ||
144 | ret = -EINVAL; | 144 | ret = -EINVAL; |
145 | goto bail; | 145 | goto bail; |
146 | } | 146 | } |
@@ -153,7 +153,7 @@ static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr, | |||
153 | writeq(data, reg_addr); | 153 | writeq(data, reg_addr); |
154 | 154 | ||
155 | reg_addr++; | 155 | reg_addr++; |
156 | uaddr++; | 156 | uaddr += sizeof(u64); |
157 | } | 157 | } |
158 | ret = 0; | 158 | ret = 0; |
159 | bail: | 159 | bail: |
@@ -191,7 +191,8 @@ static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr, | |||
191 | } | 191 | } |
192 | 192 | ||
193 | reg_addr++; | 193 | reg_addr++; |
194 | uaddr++; | 194 | uaddr += sizeof(u32); |
195 | |||
195 | } | 196 | } |
196 | ret = 0; | 197 | ret = 0; |
197 | bail: | 198 | bail: |
@@ -230,7 +231,7 @@ static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr, | |||
230 | writel(data, reg_addr); | 231 | writel(data, reg_addr); |
231 | 232 | ||
232 | reg_addr++; | 233 | reg_addr++; |
233 | uaddr++; | 234 | uaddr += sizeof(u32); |
234 | } | 235 | } |
235 | ret = 0; | 236 | ret = 0; |
236 | bail: | 237 | bail: |
@@ -239,59 +240,45 @@ bail: | |||
239 | 240 | ||
240 | static int ipath_diag_open(struct inode *in, struct file *fp) | 241 | static int ipath_diag_open(struct inode *in, struct file *fp) |
241 | { | 242 | { |
243 | int unit = iminor(in) - IPATH_DIAG_MINOR_BASE; | ||
242 | struct ipath_devdata *dd; | 244 | struct ipath_devdata *dd; |
243 | int unit = 0; /* XXX this is bogus */ | ||
244 | unsigned long flags; | ||
245 | int ret; | 245 | int ret; |
246 | 246 | ||
247 | dd = ipath_lookup(unit); | ||
248 | |||
249 | mutex_lock(&ipath_mutex); | 247 | mutex_lock(&ipath_mutex); |
250 | spin_lock_irqsave(&ipath_devs_lock, flags); | ||
251 | 248 | ||
252 | if (ipath_diag_inuse) { | 249 | if (ipath_diag_inuse) { |
253 | ret = -EBUSY; | 250 | ret = -EBUSY; |
254 | goto bail; | 251 | goto bail; |
255 | } | 252 | } |
256 | 253 | ||
257 | list_for_each_entry(dd, &ipath_dev_list, ipath_list) { | 254 | dd = ipath_lookup(unit); |
258 | /* | 255 | |
259 | * we need at least one infinipath device to be present | 256 | if (dd == NULL || !(dd->ipath_flags & IPATH_PRESENT) || |
260 | * (don't use INITTED, because we want to be able to open | 257 | !dd->ipath_kregbase) { |
261 | * even if device is in freeze mode, which cleared INITTED). | 258 | ret = -ENODEV; |
262 | * There is a small amount of risk to this, which is why we | ||
263 | * also verify kregbase is set. | ||
264 | */ | ||
265 | |||
266 | if (!(dd->ipath_flags & IPATH_PRESENT) || | ||
267 | !dd->ipath_kregbase) | ||
268 | continue; | ||
269 | |||
270 | ipath_diag_inuse = 1; | ||
271 | diag_set_link = 0; | ||
272 | ret = 0; | ||
273 | goto bail; | 259 | goto bail; |
274 | } | 260 | } |
275 | 261 | ||
276 | ret = -ENODEV; | 262 | fp->private_data = dd; |
277 | 263 | ipath_diag_inuse = 1; | |
278 | bail: | 264 | diag_set_link = 0; |
279 | spin_unlock_irqrestore(&ipath_devs_lock, flags); | 265 | ret = 0; |
280 | 266 | ||
281 | /* Only expose a way to reset the device if we | 267 | /* Only expose a way to reset the device if we |
282 | make it into diag mode. */ | 268 | make it into diag mode. */ |
283 | if (ret == 0) | 269 | ipath_expose_reset(&dd->pcidev->dev); |
284 | ipath_expose_reset(&dd->pcidev->dev); | ||
285 | 270 | ||
271 | bail: | ||
286 | mutex_unlock(&ipath_mutex); | 272 | mutex_unlock(&ipath_mutex); |
287 | 273 | ||
288 | return ret; | 274 | return ret; |
289 | } | 275 | } |
290 | 276 | ||
291 | static int ipath_diag_release(struct inode *i, struct file *f) | 277 | static int ipath_diag_release(struct inode *in, struct file *fp) |
292 | { | 278 | { |
293 | mutex_lock(&ipath_mutex); | 279 | mutex_lock(&ipath_mutex); |
294 | ipath_diag_inuse = 0; | 280 | ipath_diag_inuse = 0; |
281 | fp->private_data = NULL; | ||
295 | mutex_unlock(&ipath_mutex); | 282 | mutex_unlock(&ipath_mutex); |
296 | return 0; | 283 | return 0; |
297 | } | 284 | } |
@@ -299,17 +286,10 @@ static int ipath_diag_release(struct inode *i, struct file *f) | |||
299 | static ssize_t ipath_diag_read(struct file *fp, char __user *data, | 286 | static ssize_t ipath_diag_read(struct file *fp, char __user *data, |
300 | size_t count, loff_t *off) | 287 | size_t count, loff_t *off) |
301 | { | 288 | { |
302 | int unit = 0; /* XXX provide for reads on other units some day */ | 289 | struct ipath_devdata *dd = fp->private_data; |
303 | struct ipath_devdata *dd; | ||
304 | void __iomem *kreg_base; | 290 | void __iomem *kreg_base; |
305 | ssize_t ret; | 291 | ssize_t ret; |
306 | 292 | ||
307 | dd = ipath_lookup(unit); | ||
308 | if (!dd) { | ||
309 | ret = -ENODEV; | ||
310 | goto bail; | ||
311 | } | ||
312 | |||
313 | kreg_base = dd->ipath_kregbase; | 293 | kreg_base = dd->ipath_kregbase; |
314 | 294 | ||
315 | if (count == 0) | 295 | if (count == 0) |
@@ -328,23 +308,16 @@ static ssize_t ipath_diag_read(struct file *fp, char __user *data, | |||
328 | ret = count; | 308 | ret = count; |
329 | } | 309 | } |
330 | 310 | ||
331 | bail: | ||
332 | return ret; | 311 | return ret; |
333 | } | 312 | } |
334 | 313 | ||
335 | static ssize_t ipath_diag_write(struct file *fp, const char __user *data, | 314 | static ssize_t ipath_diag_write(struct file *fp, const char __user *data, |
336 | size_t count, loff_t *off) | 315 | size_t count, loff_t *off) |
337 | { | 316 | { |
338 | int unit = 0; /* XXX this is bogus */ | 317 | struct ipath_devdata *dd = fp->private_data; |
339 | struct ipath_devdata *dd; | ||
340 | void __iomem *kreg_base; | 318 | void __iomem *kreg_base; |
341 | ssize_t ret; | 319 | ssize_t ret; |
342 | 320 | ||
343 | dd = ipath_lookup(unit); | ||
344 | if (!dd) { | ||
345 | ret = -ENODEV; | ||
346 | goto bail; | ||
347 | } | ||
348 | kreg_base = dd->ipath_kregbase; | 321 | kreg_base = dd->ipath_kregbase; |
349 | 322 | ||
350 | if (count == 0) | 323 | if (count == 0) |
@@ -363,6 +336,5 @@ static ssize_t ipath_diag_write(struct file *fp, const char __user *data, | |||
363 | ret = count; | 336 | ret = count; |
364 | } | 337 | } |
365 | 338 | ||
366 | bail: | ||
367 | return ret; | 339 | return ret; |
368 | } | 340 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index e4b897fa569a..6efc56bce921 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -38,8 +39,8 @@ | |||
38 | #include <linux/vmalloc.h> | 39 | #include <linux/vmalloc.h> |
39 | 40 | ||
40 | #include "ipath_kernel.h" | 41 | #include "ipath_kernel.h" |
41 | #include "ips_common.h" | ||
42 | #include "ipath_layer.h" | 42 | #include "ipath_layer.h" |
43 | #include "ipath_common.h" | ||
43 | 44 | ||
44 | static void ipath_update_pio_bufs(struct ipath_devdata *); | 45 | static void ipath_update_pio_bufs(struct ipath_devdata *); |
45 | 46 | ||
@@ -52,7 +53,7 @@ const char *ipath_get_unit_name(int unit) | |||
52 | 53 | ||
53 | EXPORT_SYMBOL_GPL(ipath_get_unit_name); | 54 | EXPORT_SYMBOL_GPL(ipath_get_unit_name); |
54 | 55 | ||
55 | #define DRIVER_LOAD_MSG "PathScale " IPATH_DRV_NAME " loaded: " | 56 | #define DRIVER_LOAD_MSG "QLogic " IPATH_DRV_NAME " loaded: " |
56 | #define PFX IPATH_DRV_NAME ": " | 57 | #define PFX IPATH_DRV_NAME ": " |
57 | 58 | ||
58 | /* | 59 | /* |
@@ -74,8 +75,8 @@ MODULE_PARM_DESC(debug, "mask for debug prints"); | |||
74 | EXPORT_SYMBOL_GPL(ipath_debug); | 75 | EXPORT_SYMBOL_GPL(ipath_debug); |
75 | 76 | ||
76 | MODULE_LICENSE("GPL"); | 77 | MODULE_LICENSE("GPL"); |
77 | MODULE_AUTHOR("PathScale <support@pathscale.com>"); | 78 | MODULE_AUTHOR("QLogic <support@pathscale.com>"); |
78 | MODULE_DESCRIPTION("Pathscale InfiniPath driver"); | 79 | MODULE_DESCRIPTION("QLogic InfiniPath driver"); |
79 | 80 | ||
80 | const char *ipath_ibcstatus_str[] = { | 81 | const char *ipath_ibcstatus_str[] = { |
81 | "Disabled", | 82 | "Disabled", |
@@ -130,14 +131,6 @@ static struct pci_driver ipath_driver = { | |||
130 | .id_table = ipath_pci_tbl, | 131 | .id_table = ipath_pci_tbl, |
131 | }; | 132 | }; |
132 | 133 | ||
133 | /* | ||
134 | * This is where port 0's rcvhdrtail register is written back; we also | ||
135 | * want nothing else sharing the cache line, so make it a cache line | ||
136 | * in size. Used for all units. | ||
137 | */ | ||
138 | volatile __le64 *ipath_port0_rcvhdrtail; | ||
139 | dma_addr_t ipath_port0_rcvhdrtail_dma; | ||
140 | static int port0_rcvhdrtail_refs; | ||
141 | 134 | ||
142 | static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, | 135 | static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, |
143 | u32 *bar0, u32 *bar1) | 136 | u32 *bar0, u32 *bar1) |
@@ -170,14 +163,13 @@ static void ipath_free_devdata(struct pci_dev *pdev, | |||
170 | list_del(&dd->ipath_list); | 163 | list_del(&dd->ipath_list); |
171 | spin_unlock_irqrestore(&ipath_devs_lock, flags); | 164 | spin_unlock_irqrestore(&ipath_devs_lock, flags); |
172 | } | 165 | } |
173 | dma_free_coherent(&pdev->dev, sizeof(*dd), dd, dd->ipath_dma_addr); | 166 | vfree(dd); |
174 | } | 167 | } |
175 | 168 | ||
176 | static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev) | 169 | static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev) |
177 | { | 170 | { |
178 | unsigned long flags; | 171 | unsigned long flags; |
179 | struct ipath_devdata *dd; | 172 | struct ipath_devdata *dd; |
180 | dma_addr_t dma_addr; | ||
181 | int ret; | 173 | int ret; |
182 | 174 | ||
183 | if (!idr_pre_get(&unit_table, GFP_KERNEL)) { | 175 | if (!idr_pre_get(&unit_table, GFP_KERNEL)) { |
@@ -185,15 +177,12 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev) | |||
185 | goto bail; | 177 | goto bail; |
186 | } | 178 | } |
187 | 179 | ||
188 | dd = dma_alloc_coherent(&pdev->dev, sizeof(*dd), &dma_addr, | 180 | dd = vmalloc(sizeof(*dd)); |
189 | GFP_KERNEL); | ||
190 | |||
191 | if (!dd) { | 181 | if (!dd) { |
192 | dd = ERR_PTR(-ENOMEM); | 182 | dd = ERR_PTR(-ENOMEM); |
193 | goto bail; | 183 | goto bail; |
194 | } | 184 | } |
195 | 185 | memset(dd, 0, sizeof(*dd)); | |
196 | dd->ipath_dma_addr = dma_addr; | ||
197 | dd->ipath_unit = -1; | 186 | dd->ipath_unit = -1; |
198 | 187 | ||
199 | spin_lock_irqsave(&ipath_devs_lock, flags); | 188 | spin_lock_irqsave(&ipath_devs_lock, flags); |
@@ -271,47 +260,6 @@ int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp) | |||
271 | return nunits; | 260 | return nunits; |
272 | } | 261 | } |
273 | 262 | ||
274 | static int init_port0_rcvhdrtail(struct pci_dev *pdev) | ||
275 | { | ||
276 | int ret; | ||
277 | |||
278 | mutex_lock(&ipath_mutex); | ||
279 | |||
280 | if (!ipath_port0_rcvhdrtail) { | ||
281 | ipath_port0_rcvhdrtail = | ||
282 | dma_alloc_coherent(&pdev->dev, | ||
283 | IPATH_PORT0_RCVHDRTAIL_SIZE, | ||
284 | &ipath_port0_rcvhdrtail_dma, | ||
285 | GFP_KERNEL); | ||
286 | |||
287 | if (!ipath_port0_rcvhdrtail) { | ||
288 | ret = -ENOMEM; | ||
289 | goto bail; | ||
290 | } | ||
291 | } | ||
292 | port0_rcvhdrtail_refs++; | ||
293 | ret = 0; | ||
294 | |||
295 | bail: | ||
296 | mutex_unlock(&ipath_mutex); | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static void cleanup_port0_rcvhdrtail(struct pci_dev *pdev) | ||
302 | { | ||
303 | mutex_lock(&ipath_mutex); | ||
304 | |||
305 | if (!--port0_rcvhdrtail_refs) { | ||
306 | dma_free_coherent(&pdev->dev, IPATH_PORT0_RCVHDRTAIL_SIZE, | ||
307 | (void *) ipath_port0_rcvhdrtail, | ||
308 | ipath_port0_rcvhdrtail_dma); | ||
309 | ipath_port0_rcvhdrtail = NULL; | ||
310 | } | ||
311 | |||
312 | mutex_unlock(&ipath_mutex); | ||
313 | } | ||
314 | |||
315 | /* | 263 | /* |
316 | * These next two routines are placeholders in case we don't have per-arch | 264 | * These next two routines are placeholders in case we don't have per-arch |
317 | * code for controlling write combining. If explicit control of write | 265 | * code for controlling write combining. If explicit control of write |
@@ -336,20 +284,12 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
336 | u32 bar0 = 0, bar1 = 0; | 284 | u32 bar0 = 0, bar1 = 0; |
337 | u8 rev; | 285 | u8 rev; |
338 | 286 | ||
339 | ret = init_port0_rcvhdrtail(pdev); | ||
340 | if (ret < 0) { | ||
341 | printk(KERN_ERR IPATH_DRV_NAME | ||
342 | ": Could not allocate port0_rcvhdrtail: error %d\n", | ||
343 | -ret); | ||
344 | goto bail; | ||
345 | } | ||
346 | |||
347 | dd = ipath_alloc_devdata(pdev); | 287 | dd = ipath_alloc_devdata(pdev); |
348 | if (IS_ERR(dd)) { | 288 | if (IS_ERR(dd)) { |
349 | ret = PTR_ERR(dd); | 289 | ret = PTR_ERR(dd); |
350 | printk(KERN_ERR IPATH_DRV_NAME | 290 | printk(KERN_ERR IPATH_DRV_NAME |
351 | ": Could not allocate devdata: error %d\n", -ret); | 291 | ": Could not allocate devdata: error %d\n", -ret); |
352 | goto bail_rcvhdrtail; | 292 | goto bail; |
353 | } | 293 | } |
354 | 294 | ||
355 | ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit); | 295 | ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit); |
@@ -424,12 +364,29 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
424 | */ | 364 | */ |
425 | ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 365 | ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
426 | if (ret) { | 366 | if (ret) { |
427 | dev_info(&pdev->dev, "pci_set_dma_mask unit %u " | 367 | dev_info(&pdev->dev, |
428 | "fails: %d\n", dd->ipath_unit, ret); | 368 | "Unable to set DMA mask for unit %u: %d\n", |
369 | dd->ipath_unit, ret); | ||
429 | goto bail_regions; | 370 | goto bail_regions; |
430 | } | 371 | } |
431 | else | 372 | else { |
432 | ipath_dbg("No 64bit DMA mask, used 32 bit mask\n"); | 373 | ipath_dbg("No 64bit DMA mask, used 32 bit mask\n"); |
374 | ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | ||
375 | if (ret) | ||
376 | dev_info(&pdev->dev, | ||
377 | "Unable to set DMA consistent mask " | ||
378 | "for unit %u: %d\n", | ||
379 | dd->ipath_unit, ret); | ||
380 | |||
381 | } | ||
382 | } | ||
383 | else { | ||
384 | ret = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); | ||
385 | if (ret) | ||
386 | dev_info(&pdev->dev, | ||
387 | "Unable to set DMA consistent mask " | ||
388 | "for unit %u: %d\n", | ||
389 | dd->ipath_unit, ret); | ||
433 | } | 390 | } |
434 | 391 | ||
435 | pci_set_master(pdev); | 392 | pci_set_master(pdev); |
@@ -452,7 +409,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
452 | ipath_init_pe800_funcs(dd); | 409 | ipath_init_pe800_funcs(dd); |
453 | break; | 410 | break; |
454 | default: | 411 | default: |
455 | ipath_dev_err(dd, "Found unknown PathScale deviceid 0x%x, " | 412 | ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, " |
456 | "failing\n", ent->device); | 413 | "failing\n", ent->device); |
457 | return -ENODEV; | 414 | return -ENODEV; |
458 | } | 415 | } |
@@ -495,16 +452,16 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
495 | ((void __iomem *)dd->ipath_kregbase + len); | 452 | ((void __iomem *)dd->ipath_kregbase + len); |
496 | dd->ipath_physaddr = addr; /* used for io_remap, etc. */ | 453 | dd->ipath_physaddr = addr; /* used for io_remap, etc. */ |
497 | /* for user mmap */ | 454 | /* for user mmap */ |
498 | dd->ipath_kregvirt = (u64 __iomem *) phys_to_virt(addr); | 455 | ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p\n", |
499 | ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p " | 456 | addr, dd->ipath_kregbase); |
500 | "kregvirt %p\n", addr, dd->ipath_kregbase, | ||
501 | dd->ipath_kregvirt); | ||
502 | 457 | ||
503 | /* | 458 | /* |
504 | * clear ipath_flags here instead of in ipath_init_chip as it is set | 459 | * clear ipath_flags here instead of in ipath_init_chip as it is set |
505 | * by ipath_setup_htconfig. | 460 | * by ipath_setup_htconfig. |
506 | */ | 461 | */ |
507 | dd->ipath_flags = 0; | 462 | dd->ipath_flags = 0; |
463 | dd->ipath_lli_counter = 0; | ||
464 | dd->ipath_lli_errors = 0; | ||
508 | 465 | ||
509 | if (dd->ipath_f_bus(dd, pdev)) | 466 | if (dd->ipath_f_bus(dd, pdev)) |
510 | ipath_dev_err(dd, "Failed to setup config space; " | 467 | ipath_dev_err(dd, "Failed to setup config space; " |
@@ -545,6 +502,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
545 | ipath_device_create_group(&pdev->dev, dd); | 502 | ipath_device_create_group(&pdev->dev, dd); |
546 | ipathfs_add_device(dd); | 503 | ipathfs_add_device(dd); |
547 | ipath_user_add(dd); | 504 | ipath_user_add(dd); |
505 | ipath_diag_add(dd); | ||
548 | ipath_layer_add(dd); | 506 | ipath_layer_add(dd); |
549 | 507 | ||
550 | goto bail; | 508 | goto bail; |
@@ -561,9 +519,6 @@ bail_disable: | |||
561 | bail_devdata: | 519 | bail_devdata: |
562 | ipath_free_devdata(pdev, dd); | 520 | ipath_free_devdata(pdev, dd); |
563 | 521 | ||
564 | bail_rcvhdrtail: | ||
565 | cleanup_port0_rcvhdrtail(pdev); | ||
566 | |||
567 | bail: | 522 | bail: |
568 | return ret; | 523 | return ret; |
569 | } | 524 | } |
@@ -577,8 +532,9 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev) | |||
577 | return; | 532 | return; |
578 | 533 | ||
579 | dd = pci_get_drvdata(pdev); | 534 | dd = pci_get_drvdata(pdev); |
580 | ipath_layer_del(dd); | 535 | ipath_layer_remove(dd); |
581 | ipath_user_del(dd); | 536 | ipath_diag_remove(dd); |
537 | ipath_user_remove(dd); | ||
582 | ipathfs_remove_device(dd); | 538 | ipathfs_remove_device(dd); |
583 | ipath_device_remove_group(&pdev->dev, dd); | 539 | ipath_device_remove_group(&pdev->dev, dd); |
584 | ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, " | 540 | ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, " |
@@ -594,7 +550,6 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev) | |||
594 | pci_disable_device(pdev); | 550 | pci_disable_device(pdev); |
595 | 551 | ||
596 | ipath_free_devdata(pdev, dd); | 552 | ipath_free_devdata(pdev, dd); |
597 | cleanup_port0_rcvhdrtail(pdev); | ||
598 | } | 553 | } |
599 | 554 | ||
600 | /* general driver use */ | 555 | /* general driver use */ |
@@ -868,7 +823,8 @@ static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail, | |||
868 | u8 pad, *bthbytes; | 823 | u8 pad, *bthbytes; |
869 | struct sk_buff *skb, *nskb; | 824 | struct sk_buff *skb, *nskb; |
870 | 825 | ||
871 | if (dd->ipath_port0_skbs && hdr->sub_opcode == OPCODE_ENCAP) { | 826 | if (dd->ipath_port0_skbs && |
827 | hdr->sub_opcode == IPATH_ITH4X_OPCODE_ENCAP) { | ||
872 | /* | 828 | /* |
873 | * Allocate a new sk_buff to replace the one we give | 829 | * Allocate a new sk_buff to replace the one we give |
874 | * to the network stack. | 830 | * to the network stack. |
@@ -899,7 +855,7 @@ static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail, | |||
899 | /* another ether packet received */ | 855 | /* another ether packet received */ |
900 | ipath_stats.sps_ether_rpkts++; | 856 | ipath_stats.sps_ether_rpkts++; |
901 | } | 857 | } |
902 | else if (hdr->sub_opcode == OPCODE_LID_ARP) | 858 | else if (hdr->sub_opcode == IPATH_ITH4X_OPCODE_LID_ARP) |
903 | __ipath_layer_rcv_lid(dd, hdr); | 859 | __ipath_layer_rcv_lid(dd, hdr); |
904 | } | 860 | } |
905 | 861 | ||
@@ -916,8 +872,8 @@ void ipath_kreceive(struct ipath_devdata *dd) | |||
916 | const u32 rsize = dd->ipath_rcvhdrentsize; /* words */ | 872 | const u32 rsize = dd->ipath_rcvhdrentsize; /* words */ |
917 | const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */ | 873 | const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */ |
918 | u32 etail = -1, l, hdrqtail; | 874 | u32 etail = -1, l, hdrqtail; |
919 | struct ips_message_header *hdr; | 875 | struct ipath_message_header *hdr; |
920 | u32 eflags, i, etype, tlen, pkttot = 0; | 876 | u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0; |
921 | static u64 totcalls; /* stats, may eventually remove */ | 877 | static u64 totcalls; /* stats, may eventually remove */ |
922 | char emsg[128]; | 878 | char emsg[128]; |
923 | 879 | ||
@@ -931,24 +887,18 @@ void ipath_kreceive(struct ipath_devdata *dd) | |||
931 | if (test_and_set_bit(0, &dd->ipath_rcv_pending)) | 887 | if (test_and_set_bit(0, &dd->ipath_rcv_pending)) |
932 | goto bail; | 888 | goto bail; |
933 | 889 | ||
934 | if (dd->ipath_port0head == | 890 | l = dd->ipath_port0head; |
935 | (u32)le64_to_cpu(*dd->ipath_hdrqtailptr)) | 891 | hdrqtail = (u32) le64_to_cpu(*dd->ipath_hdrqtailptr); |
892 | if (l == hdrqtail) | ||
936 | goto done; | 893 | goto done; |
937 | 894 | ||
938 | gotmore: | 895 | reloop: |
939 | /* | 896 | for (i = 0; l != hdrqtail; i++) { |
940 | * read only once at start. If in flood situation, this helps | ||
941 | * performance slightly. If more arrive while we are processing, | ||
942 | * we'll come back here and do them | ||
943 | */ | ||
944 | hdrqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr); | ||
945 | |||
946 | for (i = 0, l = dd->ipath_port0head; l != hdrqtail; i++) { | ||
947 | u32 qp; | 897 | u32 qp; |
948 | u8 *bthbytes; | 898 | u8 *bthbytes; |
949 | 899 | ||
950 | rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2)); | 900 | rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2)); |
951 | hdr = (struct ips_message_header *)&rc[1]; | 901 | hdr = (struct ipath_message_header *)&rc[1]; |
952 | /* | 902 | /* |
953 | * could make a network order version of IPATH_KD_QP, and | 903 | * could make a network order version of IPATH_KD_QP, and |
954 | * do the obvious shift before masking to speed this up. | 904 | * do the obvious shift before masking to speed this up. |
@@ -956,10 +906,10 @@ gotmore: | |||
956 | qp = ntohl(hdr->bth[1]) & 0xffffff; | 906 | qp = ntohl(hdr->bth[1]) & 0xffffff; |
957 | bthbytes = (u8 *) hdr->bth; | 907 | bthbytes = (u8 *) hdr->bth; |
958 | 908 | ||
959 | eflags = ips_get_hdr_err_flags((__le32 *) rc); | 909 | eflags = ipath_hdrget_err_flags((__le32 *) rc); |
960 | etype = ips_get_rcv_type((__le32 *) rc); | 910 | etype = ipath_hdrget_rcv_type((__le32 *) rc); |
961 | /* total length */ | 911 | /* total length */ |
962 | tlen = ips_get_length_in_bytes((__le32 *) rc); | 912 | tlen = ipath_hdrget_length_in_bytes((__le32 *) rc); |
963 | ebuf = NULL; | 913 | ebuf = NULL; |
964 | if (etype != RCVHQ_RCV_TYPE_EXPECTED) { | 914 | if (etype != RCVHQ_RCV_TYPE_EXPECTED) { |
965 | /* | 915 | /* |
@@ -969,7 +919,7 @@ gotmore: | |||
969 | * set ebuf (so we try to copy data) unless the | 919 | * set ebuf (so we try to copy data) unless the |
970 | * length requires it. | 920 | * length requires it. |
971 | */ | 921 | */ |
972 | etail = ips_get_index((__le32 *) rc); | 922 | etail = ipath_hdrget_index((__le32 *) rc); |
973 | if (tlen > sizeof(*hdr) || | 923 | if (tlen > sizeof(*hdr) || |
974 | etype == RCVHQ_RCV_TYPE_NON_KD) | 924 | etype == RCVHQ_RCV_TYPE_NON_KD) |
975 | ebuf = ipath_get_egrbuf(dd, etail, 0); | 925 | ebuf = ipath_get_egrbuf(dd, etail, 0); |
@@ -981,7 +931,7 @@ gotmore: | |||
981 | */ | 931 | */ |
982 | 932 | ||
983 | if (etype != RCVHQ_RCV_TYPE_NON_KD && etype != | 933 | if (etype != RCVHQ_RCV_TYPE_NON_KD && etype != |
984 | RCVHQ_RCV_TYPE_ERROR && ips_get_ipath_ver( | 934 | RCVHQ_RCV_TYPE_ERROR && ipath_hdrget_ipath_ver( |
985 | hdr->iph.ver_port_tid_offset) != | 935 | hdr->iph.ver_port_tid_offset) != |
986 | IPS_PROTO_VERSION) { | 936 | IPS_PROTO_VERSION) { |
987 | ipath_cdbg(PKT, "Bad InfiniPath protocol version " | 937 | ipath_cdbg(PKT, "Bad InfiniPath protocol version " |
@@ -994,7 +944,19 @@ gotmore: | |||
994 | ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " | 944 | ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " |
995 | "tlen=%x opcode=%x egridx=%x: %s\n", | 945 | "tlen=%x opcode=%x egridx=%x: %s\n", |
996 | eflags, l, etype, tlen, bthbytes[0], | 946 | eflags, l, etype, tlen, bthbytes[0], |
997 | ips_get_index((__le32 *) rc), emsg); | 947 | ipath_hdrget_index((__le32 *) rc), emsg); |
948 | /* Count local link integrity errors. */ | ||
949 | if (eflags & (INFINIPATH_RHF_H_ICRCERR | | ||
950 | INFINIPATH_RHF_H_VCRCERR)) { | ||
951 | u8 n = (dd->ipath_ibcctrl >> | ||
952 | INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & | ||
953 | INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; | ||
954 | |||
955 | if (++dd->ipath_lli_counter > n) { | ||
956 | dd->ipath_lli_counter = 0; | ||
957 | dd->ipath_lli_errors++; | ||
958 | } | ||
959 | } | ||
998 | } else if (etype == RCVHQ_RCV_TYPE_NON_KD) { | 960 | } else if (etype == RCVHQ_RCV_TYPE_NON_KD) { |
999 | int ret = __ipath_verbs_rcv(dd, rc + 1, | 961 | int ret = __ipath_verbs_rcv(dd, rc + 1, |
1000 | ebuf, tlen); | 962 | ebuf, tlen); |
@@ -1002,6 +964,9 @@ gotmore: | |||
1002 | ipath_cdbg(VERBOSE, | 964 | ipath_cdbg(VERBOSE, |
1003 | "received IB packet, " | 965 | "received IB packet, " |
1004 | "not SMA (QP=%x)\n", qp); | 966 | "not SMA (QP=%x)\n", qp); |
967 | if (dd->ipath_lli_counter) | ||
968 | dd->ipath_lli_counter--; | ||
969 | |||
1005 | } else if (etype == RCVHQ_RCV_TYPE_EAGER) { | 970 | } else if (etype == RCVHQ_RCV_TYPE_EAGER) { |
1006 | if (qp == IPATH_KD_QP && | 971 | if (qp == IPATH_KD_QP && |
1007 | bthbytes[0] == ipath_layer_rcv_opcode && | 972 | bthbytes[0] == ipath_layer_rcv_opcode && |
@@ -1054,25 +1019,49 @@ gotmore: | |||
1054 | l += rsize; | 1019 | l += rsize; |
1055 | if (l >= maxcnt) | 1020 | if (l >= maxcnt) |
1056 | l = 0; | 1021 | l = 0; |
1022 | if (etype != RCVHQ_RCV_TYPE_EXPECTED) | ||
1023 | updegr = 1; | ||
1057 | /* | 1024 | /* |
1058 | * update for each packet, to help prevent overflows if we | 1025 | * update head regs on last packet, and every 16 packets. |
1059 | * have lots of packets. | 1026 | * Reduce bus traffic, while still trying to prevent |
1027 | * rcvhdrq overflows, for when the queue is nearly full | ||
1060 | */ | 1028 | */ |
1061 | (void)ipath_write_ureg(dd, ur_rcvhdrhead, | 1029 | if (l == hdrqtail || (i && !(i&0xf))) { |
1062 | dd->ipath_rhdrhead_intr_off | l, 0); | 1030 | u64 lval; |
1063 | if (etype != RCVHQ_RCV_TYPE_EXPECTED) | 1031 | if (l == hdrqtail) /* PE-800 interrupt only on last */ |
1064 | (void)ipath_write_ureg(dd, ur_rcvegrindexhead, | 1032 | lval = dd->ipath_rhdrhead_intr_off | l; |
1065 | etail, 0); | 1033 | else |
1034 | lval = l; | ||
1035 | (void)ipath_write_ureg(dd, ur_rcvhdrhead, lval, 0); | ||
1036 | if (updegr) { | ||
1037 | (void)ipath_write_ureg(dd, ur_rcvegrindexhead, | ||
1038 | etail, 0); | ||
1039 | updegr = 0; | ||
1040 | } | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | if (!dd->ipath_rhdrhead_intr_off && !reloop) { | ||
1045 | /* HT-400 workaround; we can have a race clearing chip | ||
1046 | * interrupt with another interrupt about to be delivered, | ||
1047 | * and can clear it before it is delivered on the GPIO | ||
1048 | * workaround. By doing the extra check here for the | ||
1049 | * in-memory tail register updating while we were doing | ||
1050 | * earlier packets, we "almost" guarantee we have covered | ||
1051 | * that case. | ||
1052 | */ | ||
1053 | u32 hqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr); | ||
1054 | if (hqtail != hdrqtail) { | ||
1055 | hdrqtail = hqtail; | ||
1056 | reloop = 1; /* loop 1 extra time at most */ | ||
1057 | goto reloop; | ||
1058 | } | ||
1066 | } | 1059 | } |
1067 | 1060 | ||
1068 | pkttot += i; | 1061 | pkttot += i; |
1069 | 1062 | ||
1070 | dd->ipath_port0head = l; | 1063 | dd->ipath_port0head = l; |
1071 | 1064 | ||
1072 | if (hdrqtail != (u32)le64_to_cpu(*dd->ipath_hdrqtailptr)) | ||
1073 | /* more arrived while we handled first batch */ | ||
1074 | goto gotmore; | ||
1075 | |||
1076 | if (pkttot > ipath_stats.sps_maxpkts_call) | 1065 | if (pkttot > ipath_stats.sps_maxpkts_call) |
1077 | ipath_stats.sps_maxpkts_call = pkttot; | 1066 | ipath_stats.sps_maxpkts_call = pkttot; |
1078 | ipath_stats.sps_port0pkts += pkttot; | 1067 | ipath_stats.sps_port0pkts += pkttot; |
@@ -1369,26 +1358,20 @@ bail: | |||
1369 | * @dd: the infinipath device | 1358 | * @dd: the infinipath device |
1370 | * @pd: the port data | 1359 | * @pd: the port data |
1371 | * | 1360 | * |
1372 | * this *must* be physically contiguous memory, and for now, | 1361 | * this must be contiguous memory (from an i/o perspective), and must be |
1373 | * that limits it to what kmalloc can do. | 1362 | * DMA'able (which means for some systems, it will go through an IOMMU, |
1363 | * or be forced into a low address range). | ||
1374 | */ | 1364 | */ |
1375 | int ipath_create_rcvhdrq(struct ipath_devdata *dd, | 1365 | int ipath_create_rcvhdrq(struct ipath_devdata *dd, |
1376 | struct ipath_portdata *pd) | 1366 | struct ipath_portdata *pd) |
1377 | { | 1367 | { |
1378 | int ret = 0, amt; | 1368 | int ret = 0; |
1379 | 1369 | ||
1380 | amt = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * | ||
1381 | sizeof(u32), PAGE_SIZE); | ||
1382 | if (!pd->port_rcvhdrq) { | 1370 | if (!pd->port_rcvhdrq) { |
1383 | /* | 1371 | dma_addr_t phys_hdrqtail; |
1384 | * not using REPEAT isn't viable; at 128KB, we can easily | ||
1385 | * fail this. The problem with REPEAT is we can block here | ||
1386 | * "forever". There isn't an inbetween, unfortunately. We | ||
1387 | * could reduce the risk by never freeing the rcvhdrq except | ||
1388 | * at unload, but even then, the first time a port is used, | ||
1389 | * we could delay for some time... | ||
1390 | */ | ||
1391 | gfp_t gfp_flags = GFP_USER | __GFP_COMP; | 1372 | gfp_t gfp_flags = GFP_USER | __GFP_COMP; |
1373 | int amt = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * | ||
1374 | sizeof(u32), PAGE_SIZE); | ||
1392 | 1375 | ||
1393 | pd->port_rcvhdrq = dma_alloc_coherent( | 1376 | pd->port_rcvhdrq = dma_alloc_coherent( |
1394 | &dd->pcidev->dev, amt, &pd->port_rcvhdrq_phys, | 1377 | &dd->pcidev->dev, amt, &pd->port_rcvhdrq_phys, |
@@ -1401,6 +1384,16 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd, | |||
1401 | ret = -ENOMEM; | 1384 | ret = -ENOMEM; |
1402 | goto bail; | 1385 | goto bail; |
1403 | } | 1386 | } |
1387 | pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent( | ||
1388 | &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, GFP_KERNEL); | ||
1389 | if (!pd->port_rcvhdrtail_kvaddr) { | ||
1390 | ipath_dev_err(dd, "attempt to allocate 1 page " | ||
1391 | "for port %u rcvhdrqtailaddr failed\n", | ||
1392 | pd->port_port); | ||
1393 | ret = -ENOMEM; | ||
1394 | goto bail; | ||
1395 | } | ||
1396 | pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail; | ||
1404 | 1397 | ||
1405 | pd->port_rcvhdrq_size = amt; | 1398 | pd->port_rcvhdrq_size = amt; |
1406 | 1399 | ||
@@ -1410,20 +1403,28 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd, | |||
1410 | (unsigned long) pd->port_rcvhdrq_phys, | 1403 | (unsigned long) pd->port_rcvhdrq_phys, |
1411 | (unsigned long) pd->port_rcvhdrq_size, | 1404 | (unsigned long) pd->port_rcvhdrq_size, |
1412 | pd->port_port); | 1405 | pd->port_port); |
1413 | } else { | 1406 | |
1414 | /* | 1407 | ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx physical\n", |
1415 | * clear for security, sanity, and/or debugging, each | 1408 | pd->port_port, |
1416 | * time we reuse | 1409 | (unsigned long long) phys_hdrqtail); |
1417 | */ | ||
1418 | memset(pd->port_rcvhdrq, 0, amt); | ||
1419 | } | 1410 | } |
1411 | else | ||
1412 | ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; " | ||
1413 | "hdrtailaddr@%p %llx physical\n", | ||
1414 | pd->port_port, pd->port_rcvhdrq, | ||
1415 | pd->port_rcvhdrq_phys, pd->port_rcvhdrtail_kvaddr, | ||
1416 | (unsigned long long)pd->port_rcvhdrqtailaddr_phys); | ||
1417 | |||
1418 | /* clear for security and sanity on each use */ | ||
1419 | memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size); | ||
1420 | memset((void *)pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE); | ||
1420 | 1421 | ||
1421 | /* | 1422 | /* |
1422 | * tell chip each time we init it, even if we are re-using previous | 1423 | * tell chip each time we init it, even if we are re-using previous |
1423 | * memory (we zero it at process close) | 1424 | * memory (we zero the register at process close) |
1424 | */ | 1425 | */ |
1425 | ipath_cdbg(VERBOSE, "writing port %d rcvhdraddr as %lx\n", | 1426 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr, |
1426 | pd->port_port, (unsigned long) pd->port_rcvhdrq_phys); | 1427 | pd->port_port, pd->port_rcvhdrqtailaddr_phys); |
1427 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr, | 1428 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr, |
1428 | pd->port_port, pd->port_rcvhdrq_phys); | 1429 | pd->port_port, pd->port_rcvhdrq_phys); |
1429 | 1430 | ||
@@ -1511,15 +1512,27 @@ void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) | |||
1511 | [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED", | 1512 | [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED", |
1512 | [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE" | 1513 | [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE" |
1513 | }; | 1514 | }; |
1515 | int linkcmd = (which >> INFINIPATH_IBCC_LINKCMD_SHIFT) & | ||
1516 | INFINIPATH_IBCC_LINKCMD_MASK; | ||
1517 | |||
1514 | ipath_cdbg(SMA, "Trying to move unit %u to %s, current ltstate " | 1518 | ipath_cdbg(SMA, "Trying to move unit %u to %s, current ltstate " |
1515 | "is %s\n", dd->ipath_unit, | 1519 | "is %s\n", dd->ipath_unit, |
1516 | what[(which >> INFINIPATH_IBCC_LINKCMD_SHIFT) & | 1520 | what[linkcmd], |
1517 | INFINIPATH_IBCC_LINKCMD_MASK], | ||
1518 | ipath_ibcstatus_str[ | 1521 | ipath_ibcstatus_str[ |
1519 | (ipath_read_kreg64 | 1522 | (ipath_read_kreg64 |
1520 | (dd, dd->ipath_kregs->kr_ibcstatus) >> | 1523 | (dd, dd->ipath_kregs->kr_ibcstatus) >> |
1521 | INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & | 1524 | INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & |
1522 | INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]); | 1525 | INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]); |
1526 | /* flush all queued sends when going to DOWN or INIT, to be sure that | ||
1527 | * they don't block SMA and other MAD packets */ | ||
1528 | if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) { | ||
1529 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
1530 | INFINIPATH_S_ABORT); | ||
1531 | ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf, | ||
1532 | (unsigned)(dd->ipath_piobcnt2k + | ||
1533 | dd->ipath_piobcnt4k) - | ||
1534 | dd->ipath_lastport_piobuf); | ||
1535 | } | ||
1523 | 1536 | ||
1524 | ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, | 1537 | ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, |
1525 | dd->ipath_ibcctrl | which); | 1538 | dd->ipath_ibcctrl | which); |
@@ -1638,7 +1651,7 @@ void ipath_shutdown_device(struct ipath_devdata *dd) | |||
1638 | /* disable IBC */ | 1651 | /* disable IBC */ |
1639 | dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; | 1652 | dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; |
1640 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | 1653 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, |
1641 | dd->ipath_control); | 1654 | dd->ipath_control | INFINIPATH_C_FREEZEMODE); |
1642 | 1655 | ||
1643 | /* | 1656 | /* |
1644 | * clear SerdesEnable and turn the leds off; do this here because | 1657 | * clear SerdesEnable and turn the leds off; do this here because |
@@ -1667,60 +1680,54 @@ void ipath_shutdown_device(struct ipath_devdata *dd) | |||
1667 | /** | 1680 | /** |
1668 | * ipath_free_pddata - free a port's allocated data | 1681 | * ipath_free_pddata - free a port's allocated data |
1669 | * @dd: the infinipath device | 1682 | * @dd: the infinipath device |
1670 | * @port: the port | 1683 | * @pd: the portdata structure |
1671 | * @freehdrq: free the port data structure if true | ||
1672 | * | 1684 | * |
1673 | * when closing, free up any allocated data for a port, if the | 1685 | * free up any allocated data for a port |
1674 | * reference count goes to zero | 1686 | * This should not touch anything that would affect a simultaneous |
1675 | * Note: this also optionally frees the portdata itself! | 1687 | * re-allocation of port data, because it is called after ipath_mutex |
1676 | * Any changes here have to be matched up with the reinit case | 1688 | * is released (and can be called from reinit as well). |
1677 | * of ipath_init_chip(), which calls this routine on reinit after reset. | 1689 | * It should never change any chip state, or global driver state. |
1690 | * (The only exception to global state is freeing the port0 port0_skbs.) | ||
1678 | */ | 1691 | */ |
1679 | void ipath_free_pddata(struct ipath_devdata *dd, u32 port, int freehdrq) | 1692 | void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd) |
1680 | { | 1693 | { |
1681 | struct ipath_portdata *pd = dd->ipath_pd[port]; | ||
1682 | |||
1683 | if (!pd) | 1694 | if (!pd) |
1684 | return; | 1695 | return; |
1685 | if (freehdrq) | 1696 | |
1686 | /* | 1697 | if (pd->port_rcvhdrq) { |
1687 | * only clear and free portdata if we are going to also | ||
1688 | * release the hdrq, otherwise we leak the hdrq on each | ||
1689 | * open/close cycle | ||
1690 | */ | ||
1691 | dd->ipath_pd[port] = NULL; | ||
1692 | if (freehdrq && pd->port_rcvhdrq) { | ||
1693 | ipath_cdbg(VERBOSE, "free closed port %d rcvhdrq @ %p " | 1698 | ipath_cdbg(VERBOSE, "free closed port %d rcvhdrq @ %p " |
1694 | "(size=%lu)\n", pd->port_port, pd->port_rcvhdrq, | 1699 | "(size=%lu)\n", pd->port_port, pd->port_rcvhdrq, |
1695 | (unsigned long) pd->port_rcvhdrq_size); | 1700 | (unsigned long) pd->port_rcvhdrq_size); |
1696 | dma_free_coherent(&dd->pcidev->dev, pd->port_rcvhdrq_size, | 1701 | dma_free_coherent(&dd->pcidev->dev, pd->port_rcvhdrq_size, |
1697 | pd->port_rcvhdrq, pd->port_rcvhdrq_phys); | 1702 | pd->port_rcvhdrq, pd->port_rcvhdrq_phys); |
1698 | pd->port_rcvhdrq = NULL; | 1703 | pd->port_rcvhdrq = NULL; |
1704 | if (pd->port_rcvhdrtail_kvaddr) { | ||
1705 | dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, | ||
1706 | (void *)pd->port_rcvhdrtail_kvaddr, | ||
1707 | pd->port_rcvhdrqtailaddr_phys); | ||
1708 | pd->port_rcvhdrtail_kvaddr = NULL; | ||
1709 | } | ||
1699 | } | 1710 | } |
1700 | if (port && pd->port_rcvegrbuf) { | 1711 | if (pd->port_port && pd->port_rcvegrbuf) { |
1701 | /* always free this */ | 1712 | unsigned e; |
1702 | if (pd->port_rcvegrbuf) { | 1713 | |
1703 | unsigned e; | 1714 | for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) { |
1704 | 1715 | void *base = pd->port_rcvegrbuf[e]; | |
1705 | for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) { | 1716 | size_t size = pd->port_rcvegrbuf_size; |
1706 | void *base = pd->port_rcvegrbuf[e]; | 1717 | |
1707 | size_t size = pd->port_rcvegrbuf_size; | 1718 | ipath_cdbg(VERBOSE, "egrbuf free(%p, %lu), " |
1708 | 1719 | "chunk %u/%u\n", base, | |
1709 | ipath_cdbg(VERBOSE, "egrbuf free(%p, %lu), " | 1720 | (unsigned long) size, |
1710 | "chunk %u/%u\n", base, | 1721 | e, pd->port_rcvegrbuf_chunks); |
1711 | (unsigned long) size, | 1722 | dma_free_coherent(&dd->pcidev->dev, size, |
1712 | e, pd->port_rcvegrbuf_chunks); | 1723 | base, pd->port_rcvegrbuf_phys[e]); |
1713 | dma_free_coherent( | ||
1714 | &dd->pcidev->dev, size, base, | ||
1715 | pd->port_rcvegrbuf_phys[e]); | ||
1716 | } | ||
1717 | vfree(pd->port_rcvegrbuf); | ||
1718 | pd->port_rcvegrbuf = NULL; | ||
1719 | vfree(pd->port_rcvegrbuf_phys); | ||
1720 | pd->port_rcvegrbuf_phys = NULL; | ||
1721 | } | 1724 | } |
1725 | vfree(pd->port_rcvegrbuf); | ||
1726 | pd->port_rcvegrbuf = NULL; | ||
1727 | vfree(pd->port_rcvegrbuf_phys); | ||
1728 | pd->port_rcvegrbuf_phys = NULL; | ||
1722 | pd->port_rcvegrbuf_chunks = 0; | 1729 | pd->port_rcvegrbuf_chunks = 0; |
1723 | } else if (port == 0 && dd->ipath_port0_skbs) { | 1730 | } else if (pd->port_port == 0 && dd->ipath_port0_skbs) { |
1724 | unsigned e; | 1731 | unsigned e; |
1725 | struct sk_buff **skbs = dd->ipath_port0_skbs; | 1732 | struct sk_buff **skbs = dd->ipath_port0_skbs; |
1726 | 1733 | ||
@@ -1732,10 +1739,8 @@ void ipath_free_pddata(struct ipath_devdata *dd, u32 port, int freehdrq) | |||
1732 | dev_kfree_skb(skbs[e]); | 1739 | dev_kfree_skb(skbs[e]); |
1733 | vfree(skbs); | 1740 | vfree(skbs); |
1734 | } | 1741 | } |
1735 | if (freehdrq) { | 1742 | kfree(pd->port_tid_pg_list); |
1736 | kfree(pd->port_tid_pg_list); | 1743 | kfree(pd); |
1737 | kfree(pd); | ||
1738 | } | ||
1739 | } | 1744 | } |
1740 | 1745 | ||
1741 | static int __init infinipath_init(void) | 1746 | static int __init infinipath_init(void) |
@@ -1806,7 +1811,6 @@ static void cleanup_device(struct ipath_devdata *dd) | |||
1806 | * re-init | 1811 | * re-init |
1807 | */ | 1812 | */ |
1808 | dd->ipath_kregbase = NULL; | 1813 | dd->ipath_kregbase = NULL; |
1809 | dd->ipath_kregvirt = NULL; | ||
1810 | dd->ipath_uregbase = 0; | 1814 | dd->ipath_uregbase = 0; |
1811 | dd->ipath_sregbase = 0; | 1815 | dd->ipath_sregbase = 0; |
1812 | dd->ipath_cregbase = 0; | 1816 | dd->ipath_cregbase = 0; |
@@ -1821,6 +1825,12 @@ static void cleanup_device(struct ipath_devdata *dd) | |||
1821 | dd->ipath_pioavailregs_phys); | 1825 | dd->ipath_pioavailregs_phys); |
1822 | dd->ipath_pioavailregs_dma = NULL; | 1826 | dd->ipath_pioavailregs_dma = NULL; |
1823 | } | 1827 | } |
1828 | if (dd->ipath_dummy_hdrq) { | ||
1829 | dma_free_coherent(&dd->pcidev->dev, | ||
1830 | dd->ipath_pd[0]->port_rcvhdrq_size, | ||
1831 | dd->ipath_dummy_hdrq, dd->ipath_dummy_hdrq_phys); | ||
1832 | dd->ipath_dummy_hdrq = NULL; | ||
1833 | } | ||
1824 | 1834 | ||
1825 | if (dd->ipath_pageshadow) { | 1835 | if (dd->ipath_pageshadow) { |
1826 | struct page **tmpp = dd->ipath_pageshadow; | 1836 | struct page **tmpp = dd->ipath_pageshadow; |
@@ -1861,10 +1871,14 @@ static void cleanup_device(struct ipath_devdata *dd) | |||
1861 | 1871 | ||
1862 | /* | 1872 | /* |
1863 | * free any resources still in use (usually just kernel ports) | 1873 | * free any resources still in use (usually just kernel ports) |
1864 | * at unload | 1874 | * at unload; we do for portcnt, not cfgports, because cfgports |
1875 | * could have changed while we were loaded. | ||
1865 | */ | 1876 | */ |
1866 | for (port = 0; port < dd->ipath_cfgports; port++) | 1877 | for (port = 0; port < dd->ipath_portcnt; port++) { |
1867 | ipath_free_pddata(dd, port, 1); | 1878 | struct ipath_portdata *pd = dd->ipath_pd[port]; |
1879 | dd->ipath_pd[port] = NULL; | ||
1880 | ipath_free_pddata(dd, pd); | ||
1881 | } | ||
1868 | kfree(dd->ipath_pd); | 1882 | kfree(dd->ipath_pd); |
1869 | /* | 1883 | /* |
1870 | * debuggability, in case some cleanup path tries to use it | 1884 | * debuggability, in case some cleanup path tries to use it |
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c index a2f1ceafcca9..3313356ab93a 100644 --- a/drivers/infiniband/hw/ipath/ipath_eeprom.c +++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -600,8 +601,31 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd) | |||
600 | guid = *(__be64 *) ifp->if_guid; | 601 | guid = *(__be64 *) ifp->if_guid; |
601 | dd->ipath_guid = guid; | 602 | dd->ipath_guid = guid; |
602 | dd->ipath_nguid = ifp->if_numguid; | 603 | dd->ipath_nguid = ifp->if_numguid; |
603 | memcpy(dd->ipath_serial, ifp->if_serial, | 604 | /* |
604 | sizeof(ifp->if_serial)); | 605 | * Things are slightly complicated by the desire to transparently |
606 | * support both the Pathscale 10-digit serial number and the QLogic | ||
607 | * 13-character version. | ||
608 | */ | ||
609 | if ((ifp->if_fversion > 1) && ifp->if_sprefix[0] | ||
610 | && ((u8 *)ifp->if_sprefix)[0] != 0xFF) { | ||
611 | /* This board has a Serial-prefix, which is stored | ||
612 | * elsewhere for backward-compatibility. | ||
613 | */ | ||
614 | char *snp = dd->ipath_serial; | ||
615 | int len; | ||
616 | memcpy(snp, ifp->if_sprefix, sizeof ifp->if_sprefix); | ||
617 | snp[sizeof ifp->if_sprefix] = '\0'; | ||
618 | len = strlen(snp); | ||
619 | snp += len; | ||
620 | len = (sizeof dd->ipath_serial) - len; | ||
621 | if (len > sizeof ifp->if_serial) { | ||
622 | len = sizeof ifp->if_serial; | ||
623 | } | ||
624 | memcpy(snp, ifp->if_serial, len); | ||
625 | } else | ||
626 | memcpy(dd->ipath_serial, ifp->if_serial, | ||
627 | sizeof ifp->if_serial); | ||
628 | |||
605 | ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n", | 629 | ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n", |
606 | (unsigned long long) be64_to_cpu(dd->ipath_guid)); | 630 | (unsigned long long) be64_to_cpu(dd->ipath_guid)); |
607 | 631 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index ada267e41f6c..bbaa70e57db1 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -38,8 +39,8 @@ | |||
38 | #include <asm/pgtable.h> | 39 | #include <asm/pgtable.h> |
39 | 40 | ||
40 | #include "ipath_kernel.h" | 41 | #include "ipath_kernel.h" |
41 | #include "ips_common.h" | ||
42 | #include "ipath_layer.h" | 42 | #include "ipath_layer.h" |
43 | #include "ipath_common.h" | ||
43 | 44 | ||
44 | static int ipath_open(struct inode *, struct file *); | 45 | static int ipath_open(struct inode *, struct file *); |
45 | static int ipath_close(struct inode *, struct file *); | 46 | static int ipath_close(struct inode *, struct file *); |
@@ -122,6 +123,7 @@ static int ipath_get_base_info(struct ipath_portdata *pd, | |||
122 | * on to yet another method of dealing with this | 123 | * on to yet another method of dealing with this |
123 | */ | 124 | */ |
124 | kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys; | 125 | kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys; |
126 | kinfo->spi_rcvhdr_tailaddr = (u64)pd->port_rcvhdrqtailaddr_phys; | ||
125 | kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys; | 127 | kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys; |
126 | kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys; | 128 | kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys; |
127 | kinfo->spi_status = (u64) kinfo->spi_pioavailaddr + | 129 | kinfo->spi_status = (u64) kinfo->spi_pioavailaddr + |
@@ -456,7 +458,7 @@ static int ipath_set_part_key(struct ipath_portdata *pd, u16 key) | |||
456 | u16 lkey = key & 0x7FFF; | 458 | u16 lkey = key & 0x7FFF; |
457 | int ret; | 459 | int ret; |
458 | 460 | ||
459 | if (lkey == (IPS_DEFAULT_P_KEY & 0x7FFF)) { | 461 | if (lkey == (IPATH_DEFAULT_P_KEY & 0x7FFF)) { |
460 | /* nothing to do; this key always valid */ | 462 | /* nothing to do; this key always valid */ |
461 | ret = 0; | 463 | ret = 0; |
462 | goto bail; | 464 | goto bail; |
@@ -704,6 +706,15 @@ static int ipath_create_user_egr(struct ipath_portdata *pd) | |||
704 | unsigned e, egrcnt, alloced, egrperchunk, chunk, egrsize, egroff; | 706 | unsigned e, egrcnt, alloced, egrperchunk, chunk, egrsize, egroff; |
705 | size_t size; | 707 | size_t size; |
706 | int ret; | 708 | int ret; |
709 | gfp_t gfp_flags; | ||
710 | |||
711 | /* | ||
712 | * GFP_USER, but without GFP_FS, so buffer cache can be | ||
713 | * coalesced (we hope); otherwise, even at order 4, | ||
714 | * heavy filesystem activity makes these fail, and we can | ||
715 | * use compound pages. | ||
716 | */ | ||
717 | gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP; | ||
707 | 718 | ||
708 | egrcnt = dd->ipath_rcvegrcnt; | 719 | egrcnt = dd->ipath_rcvegrcnt; |
709 | /* TID number offset for this port */ | 720 | /* TID number offset for this port */ |
@@ -720,10 +731,8 @@ static int ipath_create_user_egr(struct ipath_portdata *pd) | |||
720 | * memory pressure (creating large files and then copying them over | 731 | * memory pressure (creating large files and then copying them over |
721 | * NFS while doing lots of MPI jobs), we hit some allocation | 732 | * NFS while doing lots of MPI jobs), we hit some allocation |
722 | * failures, even though we can sleep... (2.6.10) Still get | 733 | * failures, even though we can sleep... (2.6.10) Still get |
723 | * failures at 64K. 32K is the lowest we can go without waiting | 734 | * failures at 64K. 32K is the lowest we can go without wasting |
724 | * more memory again. It seems likely that the coalescing in | 735 | * additional memory. |
725 | * free_pages, etc. still has issues (as it has had previously | ||
726 | * during 2.6.x development). | ||
727 | */ | 736 | */ |
728 | size = 0x8000; | 737 | size = 0x8000; |
729 | alloced = ALIGN(egrsize * egrcnt, size); | 738 | alloced = ALIGN(egrsize * egrcnt, size); |
@@ -744,12 +753,6 @@ static int ipath_create_user_egr(struct ipath_portdata *pd) | |||
744 | goto bail_rcvegrbuf; | 753 | goto bail_rcvegrbuf; |
745 | } | 754 | } |
746 | for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) { | 755 | for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) { |
747 | /* | ||
748 | * GFP_USER, but without GFP_FS, so buffer cache can be | ||
749 | * coalesced (we hope); otherwise, even at order 4, | ||
750 | * heavy filesystem activity makes these fail | ||
751 | */ | ||
752 | gfp_t gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP; | ||
753 | 756 | ||
754 | pd->port_rcvegrbuf[e] = dma_alloc_coherent( | 757 | pd->port_rcvegrbuf[e] = dma_alloc_coherent( |
755 | &dd->pcidev->dev, size, &pd->port_rcvegrbuf_phys[e], | 758 | &dd->pcidev->dev, size, &pd->port_rcvegrbuf_phys[e], |
@@ -783,11 +786,12 @@ static int ipath_create_user_egr(struct ipath_portdata *pd) | |||
783 | 786 | ||
784 | bail_rcvegrbuf_phys: | 787 | bail_rcvegrbuf_phys: |
785 | for (e = 0; e < pd->port_rcvegrbuf_chunks && | 788 | for (e = 0; e < pd->port_rcvegrbuf_chunks && |
786 | pd->port_rcvegrbuf[e]; e++) | 789 | pd->port_rcvegrbuf[e]; e++) { |
787 | dma_free_coherent(&dd->pcidev->dev, size, | 790 | dma_free_coherent(&dd->pcidev->dev, size, |
788 | pd->port_rcvegrbuf[e], | 791 | pd->port_rcvegrbuf[e], |
789 | pd->port_rcvegrbuf_phys[e]); | 792 | pd->port_rcvegrbuf_phys[e]); |
790 | 793 | ||
794 | } | ||
791 | vfree(pd->port_rcvegrbuf_phys); | 795 | vfree(pd->port_rcvegrbuf_phys); |
792 | pd->port_rcvegrbuf_phys = NULL; | 796 | pd->port_rcvegrbuf_phys = NULL; |
793 | bail_rcvegrbuf: | 797 | bail_rcvegrbuf: |
@@ -802,10 +806,7 @@ static int ipath_do_user_init(struct ipath_portdata *pd, | |||
802 | { | 806 | { |
803 | int ret = 0; | 807 | int ret = 0; |
804 | struct ipath_devdata *dd = pd->port_dd; | 808 | struct ipath_devdata *dd = pd->port_dd; |
805 | u64 physaddr, uaddr, off, atmp; | ||
806 | struct page *pagep; | ||
807 | u32 head32; | 809 | u32 head32; |
808 | u64 head; | ||
809 | 810 | ||
810 | /* for now, if major version is different, bail */ | 811 | /* for now, if major version is different, bail */ |
811 | if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) { | 812 | if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) { |
@@ -830,54 +831,6 @@ static int ipath_do_user_init(struct ipath_portdata *pd, | |||
830 | 831 | ||
831 | /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */ | 832 | /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */ |
832 | 833 | ||
833 | /* set up for the rcvhdr Q tail register writeback to user memory */ | ||
834 | if (!uinfo->spu_rcvhdraddr || | ||
835 | !access_ok(VERIFY_WRITE, (u64 __user *) (unsigned long) | ||
836 | uinfo->spu_rcvhdraddr, sizeof(u64))) { | ||
837 | ipath_dbg("Port %d rcvhdrtail addr %llx not valid\n", | ||
838 | pd->port_port, | ||
839 | (unsigned long long) uinfo->spu_rcvhdraddr); | ||
840 | ret = -EINVAL; | ||
841 | goto done; | ||
842 | } | ||
843 | |||
844 | off = offset_in_page(uinfo->spu_rcvhdraddr); | ||
845 | uaddr = PAGE_MASK & (unsigned long) uinfo->spu_rcvhdraddr; | ||
846 | ret = ipath_get_user_pages_nocopy(uaddr, &pagep); | ||
847 | if (ret) { | ||
848 | dev_info(&dd->pcidev->dev, "Failed to lookup and lock " | ||
849 | "address %llx for rcvhdrtail: errno %d\n", | ||
850 | (unsigned long long) uinfo->spu_rcvhdraddr, -ret); | ||
851 | goto done; | ||
852 | } | ||
853 | ipath_stats.sps_pagelocks++; | ||
854 | pd->port_rcvhdrtail_uaddr = uaddr; | ||
855 | pd->port_rcvhdrtail_pagep = pagep; | ||
856 | pd->port_rcvhdrtail_kvaddr = | ||
857 | page_address(pagep); | ||
858 | pd->port_rcvhdrtail_kvaddr += off; | ||
859 | physaddr = page_to_phys(pagep) + off; | ||
860 | ipath_cdbg(VERBOSE, "port %d user addr %llx hdrtailaddr, %llx " | ||
861 | "physical (off=%llx)\n", | ||
862 | pd->port_port, | ||
863 | (unsigned long long) uinfo->spu_rcvhdraddr, | ||
864 | (unsigned long long) physaddr, (unsigned long long) off); | ||
865 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr, | ||
866 | pd->port_port, physaddr); | ||
867 | atmp = ipath_read_kreg64_port(dd, | ||
868 | dd->ipath_kregs->kr_rcvhdrtailaddr, | ||
869 | pd->port_port); | ||
870 | if (physaddr != atmp) { | ||
871 | ipath_dev_err(dd, | ||
872 | "Catastrophic software error, " | ||
873 | "RcvHdrTailAddr%u written as %llx, " | ||
874 | "read back as %llx\n", pd->port_port, | ||
875 | (unsigned long long) physaddr, | ||
876 | (unsigned long long) atmp); | ||
877 | ret = -EINVAL; | ||
878 | goto done; | ||
879 | } | ||
880 | |||
881 | /* for right now, kernel piobufs are at end, so port 1 is at 0 */ | 834 | /* for right now, kernel piobufs are at end, so port 1 is at 0 */ |
882 | pd->port_piobufs = dd->ipath_piobufbase + | 835 | pd->port_piobufs = dd->ipath_piobufbase + |
883 | dd->ipath_pbufsport * (pd->port_port - | 836 | dd->ipath_pbufsport * (pd->port_port - |
@@ -896,26 +849,18 @@ static int ipath_do_user_init(struct ipath_portdata *pd, | |||
896 | ret = ipath_create_user_egr(pd); | 849 | ret = ipath_create_user_egr(pd); |
897 | if (ret) | 850 | if (ret) |
898 | goto done; | 851 | goto done; |
899 | /* enable receives now */ | ||
900 | /* atomically set enable bit for this port */ | ||
901 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, | ||
902 | &dd->ipath_rcvctrl); | ||
903 | 852 | ||
904 | /* | 853 | /* |
905 | * set the head registers for this port to the current values | 854 | * set the eager head register for this port to the current values |
906 | * of the tail pointers, since we don't know if they were | 855 | * of the tail pointers, since we don't know if they were |
907 | * updated on last use of the port. | 856 | * updated on last use of the port. |
908 | */ | 857 | */ |
909 | head32 = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); | ||
910 | head = (u64) head32; | ||
911 | ipath_write_ureg(dd, ur_rcvhdrhead, head, pd->port_port); | ||
912 | head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port); | 858 | head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port); |
913 | ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port); | 859 | ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port); |
914 | dd->ipath_lastegrheads[pd->port_port] = -1; | 860 | dd->ipath_lastegrheads[pd->port_port] = -1; |
915 | dd->ipath_lastrcvhdrqtails[pd->port_port] = -1; | 861 | dd->ipath_lastrcvhdrqtails[pd->port_port] = -1; |
916 | ipath_cdbg(VERBOSE, "Wrote port%d head %llx, egrhead %x from " | 862 | ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n", |
917 | "tail regs\n", pd->port_port, | 863 | pd->port_port, head32); |
918 | (unsigned long long) head, head32); | ||
919 | pd->port_tidcursor = 0; /* start at beginning after open */ | 864 | pd->port_tidcursor = 0; /* start at beginning after open */ |
920 | /* | 865 | /* |
921 | * now enable the port; the tail registers will be written to memory | 866 | * now enable the port; the tail registers will be written to memory |
@@ -924,24 +869,76 @@ static int ipath_do_user_init(struct ipath_portdata *pd, | |||
924 | * transition from 0 to 1, so clear it first, then set it as part of | 869 | * transition from 0 to 1, so clear it first, then set it as part of |
925 | * enabling the port. This will (very briefly) affect any other | 870 | * enabling the port. This will (very briefly) affect any other |
926 | * open ports, but it shouldn't be long enough to be an issue. | 871 | * open ports, but it shouldn't be long enough to be an issue. |
872 | * We explictly set the in-memory copy to 0 beforehand, so we don't | ||
873 | * have to wait to be sure the DMA update has happened. | ||
927 | */ | 874 | */ |
875 | *pd->port_rcvhdrtail_kvaddr = 0ULL; | ||
876 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, | ||
877 | &dd->ipath_rcvctrl); | ||
928 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 878 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, |
929 | dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD); | 879 | dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD); |
930 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 880 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, |
931 | dd->ipath_rcvctrl); | 881 | dd->ipath_rcvctrl); |
932 | |||
933 | done: | 882 | done: |
934 | return ret; | 883 | return ret; |
935 | } | 884 | } |
936 | 885 | ||
886 | |||
887 | /* common code for the mappings on dma_alloc_coherent mem */ | ||
888 | static int ipath_mmap_mem(struct vm_area_struct *vma, | ||
889 | struct ipath_portdata *pd, unsigned len, | ||
890 | int write_ok, dma_addr_t addr, char *what) | ||
891 | { | ||
892 | struct ipath_devdata *dd = pd->port_dd; | ||
893 | unsigned pfn = (unsigned long)addr >> PAGE_SHIFT; | ||
894 | int ret; | ||
895 | |||
896 | if ((vma->vm_end - vma->vm_start) > len) { | ||
897 | dev_info(&dd->pcidev->dev, | ||
898 | "FAIL on %s: len %lx > %x\n", what, | ||
899 | vma->vm_end - vma->vm_start, len); | ||
900 | ret = -EFAULT; | ||
901 | goto bail; | ||
902 | } | ||
903 | |||
904 | if (!write_ok) { | ||
905 | if (vma->vm_flags & VM_WRITE) { | ||
906 | dev_info(&dd->pcidev->dev, | ||
907 | "%s must be mapped readonly\n", what); | ||
908 | ret = -EPERM; | ||
909 | goto bail; | ||
910 | } | ||
911 | |||
912 | /* don't allow them to later change with mprotect */ | ||
913 | vma->vm_flags &= ~VM_MAYWRITE; | ||
914 | } | ||
915 | |||
916 | ret = remap_pfn_range(vma, vma->vm_start, pfn, | ||
917 | len, vma->vm_page_prot); | ||
918 | if (ret) | ||
919 | dev_info(&dd->pcidev->dev, | ||
920 | "%s port%u mmap of %lx, %x bytes r%c failed: %d\n", | ||
921 | what, pd->port_port, (unsigned long)addr, len, | ||
922 | write_ok?'w':'o', ret); | ||
923 | else | ||
924 | ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes r%c\n", | ||
925 | what, pd->port_port, (unsigned long)addr, len, | ||
926 | write_ok?'w':'o'); | ||
927 | bail: | ||
928 | return ret; | ||
929 | } | ||
930 | |||
937 | static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd, | 931 | static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd, |
938 | u64 ureg) | 932 | u64 ureg) |
939 | { | 933 | { |
940 | unsigned long phys; | 934 | unsigned long phys; |
941 | int ret; | 935 | int ret; |
942 | 936 | ||
943 | /* it's the real hardware, so io_remap works */ | 937 | /* |
944 | 938 | * This is real hardware, so use io_remap. This is the mechanism | |
939 | * for the user process to update the head registers for their port | ||
940 | * in the chip. | ||
941 | */ | ||
945 | if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) { | 942 | if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) { |
946 | dev_info(&dd->pcidev->dev, "FAIL mmap userreg: reqlen " | 943 | dev_info(&dd->pcidev->dev, "FAIL mmap userreg: reqlen " |
947 | "%lx > PAGE\n", vma->vm_end - vma->vm_start); | 944 | "%lx > PAGE\n", vma->vm_end - vma->vm_start); |
@@ -967,10 +964,11 @@ static int mmap_piobufs(struct vm_area_struct *vma, | |||
967 | int ret; | 964 | int ret; |
968 | 965 | ||
969 | /* | 966 | /* |
970 | * When we map the PIO buffers, we want to map them as writeonly, no | 967 | * When we map the PIO buffers in the chip, we want to map them as |
971 | * read possible. | 968 | * writeonly, no read possible. This prevents access to previous |
969 | * process data, and catches users who might try to read the i/o | ||
970 | * space due to a bug. | ||
972 | */ | 971 | */ |
973 | |||
974 | if ((vma->vm_end - vma->vm_start) > | 972 | if ((vma->vm_end - vma->vm_start) > |
975 | (dd->ipath_pbufsport * dd->ipath_palign)) { | 973 | (dd->ipath_pbufsport * dd->ipath_palign)) { |
976 | dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: " | 974 | dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: " |
@@ -981,11 +979,10 @@ static int mmap_piobufs(struct vm_area_struct *vma, | |||
981 | } | 979 | } |
982 | 980 | ||
983 | phys = dd->ipath_physaddr + pd->port_piobufs; | 981 | phys = dd->ipath_physaddr + pd->port_piobufs; |
982 | |||
984 | /* | 983 | /* |
985 | * Do *NOT* mark this as non-cached (PWT bit), or we don't get the | 984 | * Don't mark this as non-cached, or we don't get the |
986 | * write combining behavior we want on the PIO buffers! | 985 | * write combining behavior we want on the PIO buffers! |
987 | * vma->vm_page_prot = | ||
988 | * pgprot_noncached(vma->vm_page_prot); | ||
989 | */ | 986 | */ |
990 | 987 | ||
991 | if (vma->vm_flags & VM_READ) { | 988 | if (vma->vm_flags & VM_READ) { |
@@ -997,8 +994,7 @@ static int mmap_piobufs(struct vm_area_struct *vma, | |||
997 | } | 994 | } |
998 | 995 | ||
999 | /* don't allow them to later change to readable with mprotect */ | 996 | /* don't allow them to later change to readable with mprotect */ |
1000 | 997 | vma->vm_flags &= ~VM_MAYREAD; | |
1001 | vma->vm_flags &= ~VM_MAYWRITE; | ||
1002 | vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; | 998 | vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; |
1003 | 999 | ||
1004 | ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT, | 1000 | ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT, |
@@ -1017,11 +1013,6 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma, | |||
1017 | dma_addr_t *phys; | 1013 | dma_addr_t *phys; |
1018 | int ret; | 1014 | int ret; |
1019 | 1015 | ||
1020 | if (!pd->port_rcvegrbuf) { | ||
1021 | ret = -EFAULT; | ||
1022 | goto bail; | ||
1023 | } | ||
1024 | |||
1025 | size = pd->port_rcvegrbuf_size; | 1016 | size = pd->port_rcvegrbuf_size; |
1026 | total_size = pd->port_rcvegrbuf_chunks * size; | 1017 | total_size = pd->port_rcvegrbuf_chunks * size; |
1027 | if ((vma->vm_end - vma->vm_start) > total_size) { | 1018 | if ((vma->vm_end - vma->vm_start) > total_size) { |
@@ -1039,13 +1030,12 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma, | |||
1039 | ret = -EPERM; | 1030 | ret = -EPERM; |
1040 | goto bail; | 1031 | goto bail; |
1041 | } | 1032 | } |
1033 | /* don't allow them to later change to writeable with mprotect */ | ||
1034 | vma->vm_flags &= ~VM_MAYWRITE; | ||
1042 | 1035 | ||
1043 | start = vma->vm_start; | 1036 | start = vma->vm_start; |
1044 | phys = pd->port_rcvegrbuf_phys; | 1037 | phys = pd->port_rcvegrbuf_phys; |
1045 | 1038 | ||
1046 | /* don't allow them to later change to writeable with mprotect */ | ||
1047 | vma->vm_flags &= ~VM_MAYWRITE; | ||
1048 | |||
1049 | for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) { | 1039 | for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) { |
1050 | ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT, | 1040 | ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT, |
1051 | size, vma->vm_page_prot); | 1041 | size, vma->vm_page_prot); |
@@ -1058,78 +1048,6 @@ bail: | |||
1058 | return ret; | 1048 | return ret; |
1059 | } | 1049 | } |
1060 | 1050 | ||
1061 | static int mmap_rcvhdrq(struct vm_area_struct *vma, | ||
1062 | struct ipath_portdata *pd) | ||
1063 | { | ||
1064 | struct ipath_devdata *dd = pd->port_dd; | ||
1065 | size_t total_size; | ||
1066 | int ret; | ||
1067 | |||
1068 | /* | ||
1069 | * kmalloc'ed memory, physically contiguous; this is from | ||
1070 | * spi_rcvhdr_base; we allow user to map read-write so they can | ||
1071 | * write hdrq entries to allow protocol code to directly poll | ||
1072 | * whether a hdrq entry has been written. | ||
1073 | */ | ||
1074 | total_size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * | ||
1075 | sizeof(u32), PAGE_SIZE); | ||
1076 | if ((vma->vm_end - vma->vm_start) > total_size) { | ||
1077 | dev_info(&dd->pcidev->dev, | ||
1078 | "FAIL on rcvhdrq: reqlen %lx > actual %lx\n", | ||
1079 | vma->vm_end - vma->vm_start, | ||
1080 | (unsigned long) total_size); | ||
1081 | ret = -EFAULT; | ||
1082 | goto bail; | ||
1083 | } | ||
1084 | |||
1085 | ret = remap_pfn_range(vma, vma->vm_start, | ||
1086 | pd->port_rcvhdrq_phys >> PAGE_SHIFT, | ||
1087 | vma->vm_end - vma->vm_start, | ||
1088 | vma->vm_page_prot); | ||
1089 | bail: | ||
1090 | return ret; | ||
1091 | } | ||
1092 | |||
1093 | static int mmap_pioavailregs(struct vm_area_struct *vma, | ||
1094 | struct ipath_portdata *pd) | ||
1095 | { | ||
1096 | struct ipath_devdata *dd = pd->port_dd; | ||
1097 | int ret; | ||
1098 | |||
1099 | /* | ||
1100 | * when we map the PIO bufferavail registers, we want to map them as | ||
1101 | * readonly, no write possible. | ||
1102 | * | ||
1103 | * kmalloc'ed memory, physically contiguous, one page only, readonly | ||
1104 | */ | ||
1105 | |||
1106 | if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) { | ||
1107 | dev_info(&dd->pcidev->dev, "FAIL on pioavailregs_dma: " | ||
1108 | "reqlen %lx > actual %lx\n", | ||
1109 | vma->vm_end - vma->vm_start, | ||
1110 | (unsigned long) PAGE_SIZE); | ||
1111 | ret = -EFAULT; | ||
1112 | goto bail; | ||
1113 | } | ||
1114 | |||
1115 | if (vma->vm_flags & VM_WRITE) { | ||
1116 | dev_info(&dd->pcidev->dev, | ||
1117 | "Can't map pioavailregs as writable (flags=%lx)\n", | ||
1118 | vma->vm_flags); | ||
1119 | ret = -EPERM; | ||
1120 | goto bail; | ||
1121 | } | ||
1122 | |||
1123 | /* don't allow them to later change with mprotect */ | ||
1124 | vma->vm_flags &= ~VM_MAYWRITE; | ||
1125 | |||
1126 | ret = remap_pfn_range(vma, vma->vm_start, | ||
1127 | dd->ipath_pioavailregs_phys >> PAGE_SHIFT, | ||
1128 | PAGE_SIZE, vma->vm_page_prot); | ||
1129 | bail: | ||
1130 | return ret; | ||
1131 | } | ||
1132 | |||
1133 | /** | 1051 | /** |
1134 | * ipath_mmap - mmap various structures into user space | 1052 | * ipath_mmap - mmap various structures into user space |
1135 | * @fp: the file pointer | 1053 | * @fp: the file pointer |
@@ -1149,6 +1067,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) | |||
1149 | 1067 | ||
1150 | pd = port_fp(fp); | 1068 | pd = port_fp(fp); |
1151 | dd = pd->port_dd; | 1069 | dd = pd->port_dd; |
1070 | |||
1152 | /* | 1071 | /* |
1153 | * This is the ipath_do_user_init() code, mapping the shared buffers | 1072 | * This is the ipath_do_user_init() code, mapping the shared buffers |
1154 | * into the user process. The address referred to by vm_pgoff is the | 1073 | * into the user process. The address referred to by vm_pgoff is the |
@@ -1158,28 +1077,59 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) | |||
1158 | pgaddr = vma->vm_pgoff << PAGE_SHIFT; | 1077 | pgaddr = vma->vm_pgoff << PAGE_SHIFT; |
1159 | 1078 | ||
1160 | /* | 1079 | /* |
1161 | * note that ureg does *NOT* have the kregvirt as part of it, to be | 1080 | * Must fit in 40 bits for our hardware; some checked elsewhere, |
1162 | * sure that for 32 bit programs, we don't end up trying to map a > | 1081 | * but we'll be paranoid. Check for 0 is mostly in case one of the |
1163 | * 44 address. Has to match ipath_get_base_info() code that sets | 1082 | * allocations failed, but user called mmap anyway. We want to catch |
1164 | * __spi_uregbase | 1083 | * that before it can match. |
1165 | */ | 1084 | */ |
1085 | if (!pgaddr || pgaddr >= (1ULL<<40)) { | ||
1086 | ipath_dev_err(dd, "Bad phys addr %llx, start %lx, end %lx\n", | ||
1087 | (unsigned long long)pgaddr, vma->vm_start, vma->vm_end); | ||
1088 | return -EINVAL; | ||
1089 | } | ||
1166 | 1090 | ||
1091 | /* just the offset of the port user registers, not physical addr */ | ||
1167 | ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port; | 1092 | ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port; |
1168 | 1093 | ||
1169 | ipath_cdbg(MM, "ushare: pgaddr %llx vm_start=%lx, vmlen %lx\n", | 1094 | ipath_cdbg(MM, "ushare: pgaddr %llx vm_start=%lx, vmlen %lx\n", |
1170 | (unsigned long long) pgaddr, vma->vm_start, | 1095 | (unsigned long long) pgaddr, vma->vm_start, |
1171 | vma->vm_end - vma->vm_start); | 1096 | vma->vm_end - vma->vm_start); |
1172 | 1097 | ||
1173 | if (pgaddr == ureg) | 1098 | if (vma->vm_start & (PAGE_SIZE-1)) { |
1099 | ipath_dev_err(dd, | ||
1100 | "vm_start not aligned: %lx, end=%lx phys %lx\n", | ||
1101 | vma->vm_start, vma->vm_end, (unsigned long)pgaddr); | ||
1102 | ret = -EINVAL; | ||
1103 | } | ||
1104 | else if (pgaddr == ureg) | ||
1174 | ret = mmap_ureg(vma, dd, ureg); | 1105 | ret = mmap_ureg(vma, dd, ureg); |
1175 | else if (pgaddr == pd->port_piobufs) | 1106 | else if (pgaddr == pd->port_piobufs) |
1176 | ret = mmap_piobufs(vma, dd, pd); | 1107 | ret = mmap_piobufs(vma, dd, pd); |
1177 | else if (pgaddr == (u64) pd->port_rcvegr_phys) | 1108 | else if (pgaddr == (u64) pd->port_rcvegr_phys) |
1178 | ret = mmap_rcvegrbufs(vma, pd); | 1109 | ret = mmap_rcvegrbufs(vma, pd); |
1179 | else if (pgaddr == (u64) pd->port_rcvhdrq_phys) | 1110 | else if (pgaddr == (u64) pd->port_rcvhdrq_phys) { |
1180 | ret = mmap_rcvhdrq(vma, pd); | 1111 | /* |
1112 | * The rcvhdrq itself; readonly except on HT-400 (so have | ||
1113 | * to allow writable mapping), multiple pages, contiguous | ||
1114 | * from an i/o perspective. | ||
1115 | */ | ||
1116 | unsigned total_size = | ||
1117 | ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize | ||
1118 | * sizeof(u32), PAGE_SIZE); | ||
1119 | ret = ipath_mmap_mem(vma, pd, total_size, 1, | ||
1120 | pd->port_rcvhdrq_phys, | ||
1121 | "rcvhdrq"); | ||
1122 | } | ||
1123 | else if (pgaddr == (u64)pd->port_rcvhdrqtailaddr_phys) | ||
1124 | /* in-memory copy of rcvhdrq tail register */ | ||
1125 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, | ||
1126 | pd->port_rcvhdrqtailaddr_phys, | ||
1127 | "rcvhdrq tail"); | ||
1181 | else if (pgaddr == dd->ipath_pioavailregs_phys) | 1128 | else if (pgaddr == dd->ipath_pioavailregs_phys) |
1182 | ret = mmap_pioavailregs(vma, pd); | 1129 | /* in-memory copy of pioavail registers */ |
1130 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, | ||
1131 | dd->ipath_pioavailregs_phys, | ||
1132 | "pioavail registers"); | ||
1183 | else | 1133 | else |
1184 | ret = -EINVAL; | 1134 | ret = -EINVAL; |
1185 | 1135 | ||
@@ -1442,16 +1392,16 @@ done: | |||
1442 | 1392 | ||
1443 | static int ipath_open(struct inode *in, struct file *fp) | 1393 | static int ipath_open(struct inode *in, struct file *fp) |
1444 | { | 1394 | { |
1445 | int ret, minor; | 1395 | int ret, user_minor; |
1446 | 1396 | ||
1447 | mutex_lock(&ipath_mutex); | 1397 | mutex_lock(&ipath_mutex); |
1448 | 1398 | ||
1449 | minor = iminor(in); | 1399 | user_minor = iminor(in) - IPATH_USER_MINOR_BASE; |
1450 | ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", | 1400 | ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", |
1451 | (long)in->i_rdev, minor); | 1401 | (long)in->i_rdev, user_minor); |
1452 | 1402 | ||
1453 | if (minor) | 1403 | if (user_minor) |
1454 | ret = find_free_port(minor - 1, fp); | 1404 | ret = find_free_port(user_minor - 1, fp); |
1455 | else | 1405 | else |
1456 | ret = find_best_unit(fp); | 1406 | ret = find_best_unit(fp); |
1457 | 1407 | ||
@@ -1536,53 +1486,54 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
1536 | } | 1486 | } |
1537 | 1487 | ||
1538 | if (dd->ipath_kregbase) { | 1488 | if (dd->ipath_kregbase) { |
1539 | if (pd->port_rcvhdrtail_uaddr) { | 1489 | int i; |
1540 | pd->port_rcvhdrtail_uaddr = 0; | 1490 | /* atomically clear receive enable port. */ |
1541 | pd->port_rcvhdrtail_kvaddr = NULL; | 1491 | clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port, |
1542 | ipath_release_user_pages_on_close( | 1492 | &dd->ipath_rcvctrl); |
1543 | &pd->port_rcvhdrtail_pagep, 1); | 1493 | ipath_write_kreg( dd, dd->ipath_kregs->kr_rcvctrl, |
1544 | pd->port_rcvhdrtail_pagep = NULL; | 1494 | dd->ipath_rcvctrl); |
1545 | ipath_stats.sps_pageunlocks++; | 1495 | /* and read back from chip to be sure that nothing |
1546 | } | 1496 | * else is in flight when we do the rest */ |
1547 | ipath_write_kreg_port( | 1497 | (void)ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); |
1548 | dd, dd->ipath_kregs->kr_rcvhdrtailaddr, | ||
1549 | port, 0ULL); | ||
1550 | ipath_write_kreg_port( | ||
1551 | dd, dd->ipath_kregs->kr_rcvhdraddr, | ||
1552 | pd->port_port, 0); | ||
1553 | 1498 | ||
1554 | /* clean up the pkeys for this port user */ | 1499 | /* clean up the pkeys for this port user */ |
1555 | ipath_clean_part_key(pd, dd); | 1500 | ipath_clean_part_key(pd, dd); |
1556 | 1501 | ||
1557 | if (port < dd->ipath_cfgports) { | ||
1558 | int i = dd->ipath_pbufsport * (port - 1); | ||
1559 | ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport); | ||
1560 | 1502 | ||
1561 | /* atomically clear receive enable port. */ | 1503 | /* |
1562 | clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port, | 1504 | * be paranoid, and never write 0's to these, just use an |
1563 | &dd->ipath_rcvctrl); | 1505 | * unused part of the port 0 tail page. Of course, |
1564 | ipath_write_kreg( | 1506 | * rcvhdraddr points to a large chunk of memory, so this |
1565 | dd, | 1507 | * could still trash things, but at least it won't trash |
1566 | dd->ipath_kregs->kr_rcvctrl, | 1508 | * page 0, and by disabling the port, it should stop "soon", |
1567 | dd->ipath_rcvctrl); | 1509 | * even if a packet or two is in already in flight after we |
1568 | 1510 | * disabled the port. | |
1569 | if (dd->ipath_pageshadow) | 1511 | */ |
1570 | unlock_expected_tids(pd); | 1512 | ipath_write_kreg_port(dd, |
1571 | ipath_stats.sps_ports--; | 1513 | dd->ipath_kregs->kr_rcvhdrtailaddr, port, |
1572 | ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", | 1514 | dd->ipath_dummy_hdrq_phys); |
1573 | pd->port_comm, pd->port_pid, | 1515 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr, |
1574 | dd->ipath_unit, port); | 1516 | pd->port_port, dd->ipath_dummy_hdrq_phys); |
1575 | } | 1517 | |
1518 | i = dd->ipath_pbufsport * (port - 1); | ||
1519 | ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport); | ||
1520 | |||
1521 | if (dd->ipath_pageshadow) | ||
1522 | unlock_expected_tids(pd); | ||
1523 | ipath_stats.sps_ports--; | ||
1524 | ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", | ||
1525 | pd->port_comm, pd->port_pid, | ||
1526 | dd->ipath_unit, port); | ||
1527 | |||
1528 | dd->ipath_f_clear_tids(dd, pd->port_port); | ||
1576 | } | 1529 | } |
1577 | 1530 | ||
1578 | pd->port_cnt = 0; | 1531 | pd->port_cnt = 0; |
1579 | pd->port_pid = 0; | 1532 | pd->port_pid = 0; |
1580 | 1533 | ||
1581 | dd->ipath_f_clear_tids(dd, pd->port_port); | 1534 | dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */ |
1582 | |||
1583 | ipath_free_pddata(dd, pd->port_port, 0); | ||
1584 | |||
1585 | mutex_unlock(&ipath_mutex); | 1535 | mutex_unlock(&ipath_mutex); |
1536 | ipath_free_pddata(dd, pd); /* after releasing the mutex */ | ||
1586 | 1537 | ||
1587 | return ret; | 1538 | return ret; |
1588 | } | 1539 | } |
@@ -1859,19 +1810,12 @@ int ipath_user_add(struct ipath_devdata *dd) | |||
1859 | "error %d\n", -ret); | 1810 | "error %d\n", -ret); |
1860 | goto bail; | 1811 | goto bail; |
1861 | } | 1812 | } |
1862 | ret = ipath_diag_init(); | ||
1863 | if (ret < 0) { | ||
1864 | ipath_dev_err(dd, "Unable to set up diag support: " | ||
1865 | "error %d\n", -ret); | ||
1866 | goto bail_sma; | ||
1867 | } | ||
1868 | |||
1869 | ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev, | 1813 | ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev, |
1870 | &wildcard_class_dev); | 1814 | &wildcard_class_dev); |
1871 | if (ret < 0) { | 1815 | if (ret < 0) { |
1872 | ipath_dev_err(dd, "Could not create wildcard " | 1816 | ipath_dev_err(dd, "Could not create wildcard " |
1873 | "minor: error %d\n", -ret); | 1817 | "minor: error %d\n", -ret); |
1874 | goto bail_diag; | 1818 | goto bail_sma; |
1875 | } | 1819 | } |
1876 | 1820 | ||
1877 | atomic_set(&user_setup, 1); | 1821 | atomic_set(&user_setup, 1); |
@@ -1880,31 +1824,28 @@ int ipath_user_add(struct ipath_devdata *dd) | |||
1880 | snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit); | 1824 | snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit); |
1881 | 1825 | ||
1882 | ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops, | 1826 | ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops, |
1883 | &dd->cdev, &dd->class_dev); | 1827 | &dd->user_cdev, &dd->user_class_dev); |
1884 | if (ret < 0) | 1828 | if (ret < 0) |
1885 | ipath_dev_err(dd, "Could not create user minor %d, %s\n", | 1829 | ipath_dev_err(dd, "Could not create user minor %d, %s\n", |
1886 | dd->ipath_unit + 1, name); | 1830 | dd->ipath_unit + 1, name); |
1887 | 1831 | ||
1888 | goto bail; | 1832 | goto bail; |
1889 | 1833 | ||
1890 | bail_diag: | ||
1891 | ipath_diag_cleanup(); | ||
1892 | bail_sma: | 1834 | bail_sma: |
1893 | user_cleanup(); | 1835 | user_cleanup(); |
1894 | bail: | 1836 | bail: |
1895 | return ret; | 1837 | return ret; |
1896 | } | 1838 | } |
1897 | 1839 | ||
1898 | void ipath_user_del(struct ipath_devdata *dd) | 1840 | void ipath_user_remove(struct ipath_devdata *dd) |
1899 | { | 1841 | { |
1900 | cleanup_cdev(&dd->cdev, &dd->class_dev); | 1842 | cleanup_cdev(&dd->user_cdev, &dd->user_class_dev); |
1901 | 1843 | ||
1902 | if (atomic_dec_return(&user_count) == 0) { | 1844 | if (atomic_dec_return(&user_count) == 0) { |
1903 | if (atomic_read(&user_setup) == 0) | 1845 | if (atomic_read(&user_setup) == 0) |
1904 | goto bail; | 1846 | goto bail; |
1905 | 1847 | ||
1906 | cleanup_cdev(&wildcard_cdev, &wildcard_class_dev); | 1848 | cleanup_cdev(&wildcard_cdev, &wildcard_class_dev); |
1907 | ipath_diag_cleanup(); | ||
1908 | user_cleanup(); | 1849 | user_cleanup(); |
1909 | 1850 | ||
1910 | atomic_set(&user_setup, 0); | 1851 | atomic_set(&user_setup, 0); |
@@ -1912,3 +1853,4 @@ void ipath_user_del(struct ipath_devdata *dd) | |||
1912 | bail: | 1853 | bail: |
1913 | return; | 1854 | return; |
1914 | } | 1855 | } |
1856 | |||
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 97f142c5be13..0936d8e8d704 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
diff --git a/drivers/infiniband/hw/ipath/ipath_ht400.c b/drivers/infiniband/hw/ipath/ipath_ht400.c index fac0a2b74de2..3db015da6e77 100644 --- a/drivers/infiniband/hw/ipath/ipath_ht400.c +++ b/drivers/infiniband/hw/ipath/ipath_ht400.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -1572,7 +1573,6 @@ void ipath_init_ht400_funcs(struct ipath_devdata *dd) | |||
1572 | dd->ipath_f_reset = ipath_setup_ht_reset; | 1573 | dd->ipath_f_reset = ipath_setup_ht_reset; |
1573 | dd->ipath_f_get_boardname = ipath_ht_boardname; | 1574 | dd->ipath_f_get_boardname = ipath_ht_boardname; |
1574 | dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors; | 1575 | dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors; |
1575 | dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors; | ||
1576 | dd->ipath_f_early_init = ipath_ht_early_init; | 1576 | dd->ipath_f_early_init = ipath_ht_early_init; |
1577 | dd->ipath_f_handle_hwerrors = ipath_ht_handle_hwerrors; | 1577 | dd->ipath_f_handle_hwerrors = ipath_ht_handle_hwerrors; |
1578 | dd->ipath_f_quiet_serdes = ipath_ht_quiet_serdes; | 1578 | dd->ipath_f_quiet_serdes = ipath_ht_quiet_serdes; |
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index dc83250d26a6..414cdd1d80a6 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -35,7 +36,7 @@ | |||
35 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
36 | 37 | ||
37 | #include "ipath_kernel.h" | 38 | #include "ipath_kernel.h" |
38 | #include "ips_common.h" | 39 | #include "ipath_common.h" |
39 | 40 | ||
40 | /* | 41 | /* |
41 | * min buffers we want to have per port, after driver | 42 | * min buffers we want to have per port, after driver |
@@ -114,6 +115,7 @@ static int create_port0_egr(struct ipath_devdata *dd) | |||
114 | "eager TID %u\n", e); | 115 | "eager TID %u\n", e); |
115 | while (e != 0) | 116 | while (e != 0) |
116 | dev_kfree_skb(skbs[--e]); | 117 | dev_kfree_skb(skbs[--e]); |
118 | vfree(skbs); | ||
117 | ret = -ENOMEM; | 119 | ret = -ENOMEM; |
118 | goto bail; | 120 | goto bail; |
119 | } | 121 | } |
@@ -275,7 +277,7 @@ static int init_chip_first(struct ipath_devdata *dd, | |||
275 | pd->port_port = 0; | 277 | pd->port_port = 0; |
276 | pd->port_cnt = 1; | 278 | pd->port_cnt = 1; |
277 | /* The port 0 pkey table is used by the layer interface. */ | 279 | /* The port 0 pkey table is used by the layer interface. */ |
278 | pd->port_pkeys[0] = IPS_DEFAULT_P_KEY; | 280 | pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY; |
279 | dd->ipath_rcvtidcnt = | 281 | dd->ipath_rcvtidcnt = |
280 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); | 282 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); |
281 | dd->ipath_rcvtidbase = | 283 | dd->ipath_rcvtidbase = |
@@ -409,17 +411,8 @@ static int init_pioavailregs(struct ipath_devdata *dd) | |||
409 | /* and its length */ | 411 | /* and its length */ |
410 | dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]); | 412 | dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]); |
411 | 413 | ||
412 | if (dd->ipath_unit * 64 > (IPATH_PORT0_RCVHDRTAIL_SIZE - 64)) { | 414 | ret = 0; |
413 | ipath_dev_err(dd, "unit %u too large for port 0 " | ||
414 | "rcvhdrtail buffer size\n", dd->ipath_unit); | ||
415 | ret = -ENODEV; | ||
416 | } | ||
417 | else | ||
418 | ret = 0; | ||
419 | 415 | ||
420 | /* so we can get current tail in ipath_kreceive(), per chip */ | ||
421 | dd->ipath_hdrqtailptr = &ipath_port0_rcvhdrtail[ | ||
422 | dd->ipath_unit * (64 / sizeof(*ipath_port0_rcvhdrtail))]; | ||
423 | done: | 416 | done: |
424 | return ret; | 417 | return ret; |
425 | } | 418 | } |
@@ -652,8 +645,9 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
652 | { | 645 | { |
653 | int ret = 0, i; | 646 | int ret = 0, i; |
654 | u32 val32, kpiobufs; | 647 | u32 val32, kpiobufs; |
655 | u64 val, atmp; | 648 | u64 val; |
656 | struct ipath_portdata *pd = NULL; /* keep gcc4 happy */ | 649 | struct ipath_portdata *pd = NULL; /* keep gcc4 happy */ |
650 | gfp_t gfp_flags = GFP_USER | __GFP_COMP; | ||
657 | 651 | ||
658 | ret = init_housekeeping(dd, &pd, reinit); | 652 | ret = init_housekeeping(dd, &pd, reinit); |
659 | if (ret) | 653 | if (ret) |
@@ -775,24 +769,6 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
775 | goto done; | 769 | goto done; |
776 | } | 770 | } |
777 | 771 | ||
778 | val = ipath_port0_rcvhdrtail_dma + dd->ipath_unit * 64; | ||
779 | |||
780 | /* verify that the alignment requirement was met */ | ||
781 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr, | ||
782 | 0, val); | ||
783 | atmp = ipath_read_kreg64_port( | ||
784 | dd, dd->ipath_kregs->kr_rcvhdrtailaddr, 0); | ||
785 | if (val != atmp) { | ||
786 | ipath_dev_err(dd, "Catastrophic software error, " | ||
787 | "RcvHdrTailAddr0 written as %llx, " | ||
788 | "read back as %llx from %x\n", | ||
789 | (unsigned long long) val, | ||
790 | (unsigned long long) atmp, | ||
791 | dd->ipath_kregs->kr_rcvhdrtailaddr); | ||
792 | ret = -EINVAL; | ||
793 | goto done; | ||
794 | } | ||
795 | |||
796 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP); | 772 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP); |
797 | 773 | ||
798 | /* | 774 | /* |
@@ -836,25 +812,45 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
836 | /* clear any interrups up to this point (ints still not enabled) */ | 812 | /* clear any interrups up to this point (ints still not enabled) */ |
837 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL); | 813 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL); |
838 | 814 | ||
839 | ipath_stats.sps_lid[dd->ipath_unit] = dd->ipath_lid; | ||
840 | |||
841 | /* | 815 | /* |
842 | * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing | 816 | * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing |
843 | * re-init, the simplest way to handle this is to free | 817 | * re-init, the simplest way to handle this is to free |
844 | * existing, and re-allocate. | 818 | * existing, and re-allocate. |
845 | */ | 819 | */ |
846 | if (reinit) | 820 | if (reinit) { |
847 | ipath_free_pddata(dd, 0, 0); | 821 | struct ipath_portdata *pd = dd->ipath_pd[0]; |
822 | dd->ipath_pd[0] = NULL; | ||
823 | ipath_free_pddata(dd, pd); | ||
824 | } | ||
848 | dd->ipath_f_tidtemplate(dd); | 825 | dd->ipath_f_tidtemplate(dd); |
849 | ret = ipath_create_rcvhdrq(dd, pd); | 826 | ret = ipath_create_rcvhdrq(dd, pd); |
850 | if (!ret) | 827 | if (!ret) { |
828 | dd->ipath_hdrqtailptr = | ||
829 | (volatile __le64 *)pd->port_rcvhdrtail_kvaddr; | ||
851 | ret = create_port0_egr(dd); | 830 | ret = create_port0_egr(dd); |
831 | } | ||
852 | if (ret) | 832 | if (ret) |
853 | ipath_dev_err(dd, "failed to allocate port 0 (kernel) " | 833 | ipath_dev_err(dd, "failed to allocate port 0 (kernel) " |
854 | "rcvhdrq and/or egr bufs\n"); | 834 | "rcvhdrq and/or egr bufs\n"); |
855 | else | 835 | else |
856 | enable_chip(dd, pd, reinit); | 836 | enable_chip(dd, pd, reinit); |
857 | 837 | ||
838 | |||
839 | if (!ret && !reinit) { | ||
840 | /* used when we close a port, for DMA already in flight at close */ | ||
841 | dd->ipath_dummy_hdrq = dma_alloc_coherent( | ||
842 | &dd->pcidev->dev, pd->port_rcvhdrq_size, | ||
843 | &dd->ipath_dummy_hdrq_phys, | ||
844 | gfp_flags); | ||
845 | if (!dd->ipath_dummy_hdrq ) { | ||
846 | dev_info(&dd->pcidev->dev, | ||
847 | "Couldn't allocate 0x%lx bytes for dummy hdrq\n", | ||
848 | pd->port_rcvhdrq_size); | ||
849 | /* fallback to just 0'ing */ | ||
850 | dd->ipath_dummy_hdrq_phys = 0UL; | ||
851 | } | ||
852 | } | ||
853 | |||
858 | /* | 854 | /* |
859 | * cause retrigger of pending interrupts ignored during init, | 855 | * cause retrigger of pending interrupts ignored during init, |
860 | * even if we had errors | 856 | * even if we had errors |
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index 5e31d0de849b..280e732660a1 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -33,9 +34,10 @@ | |||
33 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
34 | 35 | ||
35 | #include "ipath_kernel.h" | 36 | #include "ipath_kernel.h" |
36 | #include "ips_common.h" | ||
37 | #include "ipath_layer.h" | 37 | #include "ipath_layer.h" |
38 | #include "ipath_common.h" | ||
38 | 39 | ||
40 | /* These are all rcv-related errors which we want to count for stats */ | ||
39 | #define E_SUM_PKTERRS \ | 41 | #define E_SUM_PKTERRS \ |
40 | (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \ | 42 | (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \ |
41 | INFINIPATH_E_RBADVERSION | INFINIPATH_E_RHDR | \ | 43 | INFINIPATH_E_RBADVERSION | INFINIPATH_E_RHDR | \ |
@@ -44,6 +46,7 @@ | |||
44 | INFINIPATH_E_RFORMATERR | INFINIPATH_E_RUNSUPVL | \ | 46 | INFINIPATH_E_RFORMATERR | INFINIPATH_E_RUNSUPVL | \ |
45 | INFINIPATH_E_RUNEXPCHAR | INFINIPATH_E_REBP) | 47 | INFINIPATH_E_RUNEXPCHAR | INFINIPATH_E_REBP) |
46 | 48 | ||
49 | /* These are all send-related errors which we want to count for stats */ | ||
47 | #define E_SUM_ERRS \ | 50 | #define E_SUM_ERRS \ |
48 | (INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | \ | 51 | (INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | \ |
49 | INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \ | 52 | INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \ |
@@ -51,6 +54,18 @@ | |||
51 | INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \ | 54 | INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \ |
52 | INFINIPATH_E_INVALIDADDR) | 55 | INFINIPATH_E_INVALIDADDR) |
53 | 56 | ||
57 | /* | ||
58 | * these are errors that can occur when the link changes state while | ||
59 | * a packet is being sent or received. This doesn't cover things | ||
60 | * like EBP or VCRC that can be the result of a sending having the | ||
61 | * link change state, so we receive a "known bad" packet. | ||
62 | */ | ||
63 | #define E_SUM_LINK_PKTERRS \ | ||
64 | (INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \ | ||
65 | INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \ | ||
66 | INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RMINPKTLEN | \ | ||
67 | INFINIPATH_E_RUNEXPCHAR) | ||
68 | |||
54 | static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) | 69 | static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) |
55 | { | 70 | { |
56 | unsigned long sbuf[4]; | 71 | unsigned long sbuf[4]; |
@@ -100,9 +115,7 @@ static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) | |||
100 | if (ipath_debug & __IPATH_PKTDBG) | 115 | if (ipath_debug & __IPATH_PKTDBG) |
101 | printk("\n"); | 116 | printk("\n"); |
102 | } | 117 | } |
103 | if ((errs & (INFINIPATH_E_SDROPPEDDATAPKT | | 118 | if ((errs & E_SUM_LINK_PKTERRS) && |
104 | INFINIPATH_E_SDROPPEDSMPPKT | | ||
105 | INFINIPATH_E_SMINPKTLEN)) && | ||
106 | !(dd->ipath_flags & IPATH_LINKACTIVE)) { | 119 | !(dd->ipath_flags & IPATH_LINKACTIVE)) { |
107 | /* | 120 | /* |
108 | * This can happen when SMA is trying to bring the link | 121 | * This can happen when SMA is trying to bring the link |
@@ -111,11 +124,9 @@ static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) | |||
111 | * valid. We don't want to confuse people, so we just | 124 | * valid. We don't want to confuse people, so we just |
112 | * don't print them, except at debug | 125 | * don't print them, except at debug |
113 | */ | 126 | */ |
114 | ipath_dbg("Ignoring pktsend errors %llx, because not " | 127 | ipath_dbg("Ignoring packet errors %llx, because link not " |
115 | "yet active\n", (unsigned long long) errs); | 128 | "ACTIVE\n", (unsigned long long) errs); |
116 | ignore_this_time = INFINIPATH_E_SDROPPEDDATAPKT | | 129 | ignore_this_time = errs & E_SUM_LINK_PKTERRS; |
117 | INFINIPATH_E_SDROPPEDSMPPKT | | ||
118 | INFINIPATH_E_SMINPKTLEN; | ||
119 | } | 130 | } |
120 | 131 | ||
121 | return ignore_this_time; | 132 | return ignore_this_time; |
@@ -156,7 +167,29 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, | |||
156 | */ | 167 | */ |
157 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); | 168 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); |
158 | lstate = val & IPATH_IBSTATE_MASK; | 169 | lstate = val & IPATH_IBSTATE_MASK; |
159 | if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM || | 170 | |
171 | /* | ||
172 | * this is confusing enough when it happens that I want to always put it | ||
173 | * on the console and in the logs. If it was a requested state change, | ||
174 | * we'll have already cleared the flags, so we won't print this warning | ||
175 | */ | ||
176 | if ((lstate != IPATH_IBSTATE_ARM && lstate != IPATH_IBSTATE_ACTIVE) | ||
177 | && (dd->ipath_flags & (IPATH_LINKARMED | IPATH_LINKACTIVE))) { | ||
178 | dev_info(&dd->pcidev->dev, "Link state changed from %s to %s\n", | ||
179 | (dd->ipath_flags & IPATH_LINKARMED) ? "ARM" : "ACTIVE", | ||
180 | ib_linkstate(lstate)); | ||
181 | /* | ||
182 | * Flush all queued sends when link went to DOWN or INIT, | ||
183 | * to be sure that they don't block SMA and other MAD packets | ||
184 | */ | ||
185 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
186 | INFINIPATH_S_ABORT); | ||
187 | ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf, | ||
188 | (unsigned)(dd->ipath_piobcnt2k + | ||
189 | dd->ipath_piobcnt4k) - | ||
190 | dd->ipath_lastport_piobuf); | ||
191 | } | ||
192 | else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM || | ||
160 | lstate == IPATH_IBSTATE_ACTIVE) { | 193 | lstate == IPATH_IBSTATE_ACTIVE) { |
161 | /* | 194 | /* |
162 | * only print at SMA if there is a change, debug if not | 195 | * only print at SMA if there is a change, debug if not |
@@ -229,6 +262,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, | |||
229 | | IPATH_LINKACTIVE | | 262 | | IPATH_LINKACTIVE | |
230 | IPATH_LINKARMED); | 263 | IPATH_LINKARMED); |
231 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; | 264 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; |
265 | dd->ipath_lli_counter = 0; | ||
232 | if (!noprint) { | 266 | if (!noprint) { |
233 | if (((dd->ipath_lastibcstat >> | 267 | if (((dd->ipath_lastibcstat >> |
234 | INFINIPATH_IBCS_LINKSTATE_SHIFT) & | 268 | INFINIPATH_IBCS_LINKSTATE_SHIFT) & |
@@ -350,7 +384,7 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd, | |||
350 | return supp_msgs; | 384 | return supp_msgs; |
351 | } | 385 | } |
352 | 386 | ||
353 | static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | 387 | static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) |
354 | { | 388 | { |
355 | char msg[512]; | 389 | char msg[512]; |
356 | u64 ignore_this_time = 0; | 390 | u64 ignore_this_time = 0; |
@@ -379,6 +413,19 @@ static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
379 | 413 | ||
380 | if (errs & E_SUM_ERRS) | 414 | if (errs & E_SUM_ERRS) |
381 | ignore_this_time = handle_e_sum_errs(dd, errs); | 415 | ignore_this_time = handle_e_sum_errs(dd, errs); |
416 | else if ((errs & E_SUM_LINK_PKTERRS) && | ||
417 | !(dd->ipath_flags & IPATH_LINKACTIVE)) { | ||
418 | /* | ||
419 | * This can happen when SMA is trying to bring the link | ||
420 | * up, but the IB link changes state at the "wrong" time. | ||
421 | * The IB logic then complains that the packet isn't | ||
422 | * valid. We don't want to confuse people, so we just | ||
423 | * don't print them, except at debug | ||
424 | */ | ||
425 | ipath_dbg("Ignoring packet errors %llx, because link not " | ||
426 | "ACTIVE\n", (unsigned long long) errs); | ||
427 | ignore_this_time = errs & E_SUM_LINK_PKTERRS; | ||
428 | } | ||
382 | 429 | ||
383 | if (supp_msgs == 250000) { | 430 | if (supp_msgs == 250000) { |
384 | /* | 431 | /* |
@@ -434,7 +481,7 @@ static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
434 | INFINIPATH_E_IBSTATUSCHANGED); | 481 | INFINIPATH_E_IBSTATUSCHANGED); |
435 | } | 482 | } |
436 | if (!errs) | 483 | if (!errs) |
437 | return; | 484 | return 0; |
438 | 485 | ||
439 | if (!noprint) | 486 | if (!noprint) |
440 | /* | 487 | /* |
@@ -493,10 +540,10 @@ static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
493 | continue; | 540 | continue; |
494 | if (hd == (tl + 1) || | 541 | if (hd == (tl + 1) || |
495 | (!hd && tl == dd->ipath_hdrqlast)) { | 542 | (!hd && tl == dd->ipath_hdrqlast)) { |
496 | dd->ipath_lastrcvhdrqtails[i] = tl; | ||
497 | pd->port_hdrqfull++; | ||
498 | if (i == 0) | 543 | if (i == 0) |
499 | chkerrpkts = 1; | 544 | chkerrpkts = 1; |
545 | dd->ipath_lastrcvhdrqtails[i] = tl; | ||
546 | pd->port_hdrqfull++; | ||
500 | } | 547 | } |
501 | } | 548 | } |
502 | } | 549 | } |
@@ -558,9 +605,7 @@ static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
558 | wake_up_interruptible(&ipath_sma_state_wait); | 605 | wake_up_interruptible(&ipath_sma_state_wait); |
559 | } | 606 | } |
560 | 607 | ||
561 | if (chkerrpkts) | 608 | return chkerrpkts; |
562 | /* process possible error packets in hdrq */ | ||
563 | ipath_kreceive(dd); | ||
564 | } | 609 | } |
565 | 610 | ||
566 | /* this is separate to allow for better optimization of ipath_intr() */ | 611 | /* this is separate to allow for better optimization of ipath_intr() */ |
@@ -678,7 +723,12 @@ set: | |||
678 | dd->ipath_sendctrl); | 723 | dd->ipath_sendctrl); |
679 | } | 724 | } |
680 | 725 | ||
681 | static void handle_rcv(struct ipath_devdata *dd, u32 istat) | 726 | /* |
727 | * Handle receive interrupts for user ports; this means a user | ||
728 | * process was waiting for a packet to arrive, and didn't want | ||
729 | * to poll | ||
730 | */ | ||
731 | static void handle_urcv(struct ipath_devdata *dd, u32 istat) | ||
682 | { | 732 | { |
683 | u64 portr; | 733 | u64 portr; |
684 | int i; | 734 | int i; |
@@ -688,22 +738,17 @@ static void handle_rcv(struct ipath_devdata *dd, u32 istat) | |||
688 | infinipath_i_rcvavail_mask) | 738 | infinipath_i_rcvavail_mask) |
689 | | ((istat >> INFINIPATH_I_RCVURG_SHIFT) & | 739 | | ((istat >> INFINIPATH_I_RCVURG_SHIFT) & |
690 | infinipath_i_rcvurg_mask); | 740 | infinipath_i_rcvurg_mask); |
691 | for (i = 0; i < dd->ipath_cfgports; i++) { | 741 | for (i = 1; i < dd->ipath_cfgports; i++) { |
692 | struct ipath_portdata *pd = dd->ipath_pd[i]; | 742 | struct ipath_portdata *pd = dd->ipath_pd[i]; |
693 | if (portr & (1 << i) && pd && | 743 | if (portr & (1 << i) && pd && pd->port_cnt && |
694 | pd->port_cnt) { | 744 | test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) { |
695 | if (i == 0) | 745 | int rcbit; |
696 | ipath_kreceive(dd); | 746 | clear_bit(IPATH_PORT_WAITING_RCV, |
697 | else if (test_bit(IPATH_PORT_WAITING_RCV, | 747 | &pd->port_flag); |
698 | &pd->port_flag)) { | 748 | rcbit = i + INFINIPATH_R_INTRAVAIL_SHIFT; |
699 | int rcbit; | 749 | clear_bit(1UL << rcbit, &dd->ipath_rcvctrl); |
700 | clear_bit(IPATH_PORT_WAITING_RCV, | 750 | wake_up_interruptible(&pd->port_wait); |
701 | &pd->port_flag); | 751 | rcvdint = 1; |
702 | rcbit = i + INFINIPATH_R_INTRAVAIL_SHIFT; | ||
703 | clear_bit(1UL << rcbit, &dd->ipath_rcvctrl); | ||
704 | wake_up_interruptible(&pd->port_wait); | ||
705 | rcvdint = 1; | ||
706 | } | ||
707 | } | 752 | } |
708 | } | 753 | } |
709 | if (rcvdint) { | 754 | if (rcvdint) { |
@@ -719,16 +764,19 @@ static void handle_rcv(struct ipath_devdata *dd, u32 istat) | |||
719 | irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | 764 | irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) |
720 | { | 765 | { |
721 | struct ipath_devdata *dd = data; | 766 | struct ipath_devdata *dd = data; |
722 | u32 istat; | 767 | u32 istat, chk0rcv = 0; |
723 | ipath_err_t estat = 0; | 768 | ipath_err_t estat = 0; |
724 | static unsigned unexpected = 0; | ||
725 | irqreturn_t ret; | 769 | irqreturn_t ret; |
770 | u32 oldhead, curtail; | ||
771 | static unsigned unexpected = 0; | ||
772 | static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) | | ||
773 | (1U<<INFINIPATH_I_RCVURG_SHIFT); | ||
774 | |||
775 | ipath_stats.sps_ints++; | ||
726 | 776 | ||
727 | if(!(dd->ipath_flags & IPATH_PRESENT)) { | 777 | if (!(dd->ipath_flags & IPATH_PRESENT)) { |
728 | /* this is mostly so we don't try to touch the chip while | ||
729 | * it is being reset */ | ||
730 | /* | 778 | /* |
731 | * This return value is perhaps odd, but we do not want the | 779 | * This return value is not great, but we do not want the |
732 | * interrupt core code to remove our interrupt handler | 780 | * interrupt core code to remove our interrupt handler |
733 | * because we don't appear to be handling an interrupt | 781 | * because we don't appear to be handling an interrupt |
734 | * during a chip reset. | 782 | * during a chip reset. |
@@ -736,7 +784,51 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
736 | return IRQ_HANDLED; | 784 | return IRQ_HANDLED; |
737 | } | 785 | } |
738 | 786 | ||
787 | /* | ||
788 | * this needs to be flags&initted, not statusp, so we keep | ||
789 | * taking interrupts even after link goes down, etc. | ||
790 | * Also, we *must* clear the interrupt at some point, or we won't | ||
791 | * take it again, which can be real bad for errors, etc... | ||
792 | */ | ||
793 | |||
794 | if (!(dd->ipath_flags & IPATH_INITTED)) { | ||
795 | ipath_bad_intr(dd, &unexpected); | ||
796 | ret = IRQ_NONE; | ||
797 | goto bail; | ||
798 | } | ||
799 | |||
800 | /* | ||
801 | * We try to avoid reading the interrupt status register, since | ||
802 | * that's a PIO read, and stalls the processor for up to about | ||
803 | * ~0.25 usec. The idea is that if we processed a port0 packet, | ||
804 | * we blindly clear the port 0 receive interrupt bits, and nothing | ||
805 | * else, then return. If other interrupts are pending, the chip | ||
806 | * will re-interrupt us as soon as we write the intclear register. | ||
807 | * We then won't process any more kernel packets (if not the 2nd | ||
808 | * time, then the 3rd or 4th) and we'll then handle the other | ||
809 | * interrupts. We clear the interrupts first so that we don't | ||
810 | * lose intr for later packets that arrive while we are processing. | ||
811 | */ | ||
812 | oldhead = dd->ipath_port0head; | ||
813 | curtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr); | ||
814 | if (oldhead != curtail) { | ||
815 | if (dd->ipath_flags & IPATH_GPIO_INTR) { | ||
816 | ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, | ||
817 | (u64) (1 << 2)); | ||
818 | istat = port0rbits | INFINIPATH_I_GPIO; | ||
819 | } | ||
820 | else | ||
821 | istat = port0rbits; | ||
822 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat); | ||
823 | ipath_kreceive(dd); | ||
824 | if (oldhead != dd->ipath_port0head) { | ||
825 | ipath_stats.sps_fastrcvint++; | ||
826 | goto done; | ||
827 | } | ||
828 | } | ||
829 | |||
739 | istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus); | 830 | istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus); |
831 | |||
740 | if (unlikely(!istat)) { | 832 | if (unlikely(!istat)) { |
741 | ipath_stats.sps_nullintr++; | 833 | ipath_stats.sps_nullintr++; |
742 | ret = IRQ_NONE; /* not our interrupt, or already handled */ | 834 | ret = IRQ_NONE; /* not our interrupt, or already handled */ |
@@ -749,31 +841,17 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
749 | goto bail; | 841 | goto bail; |
750 | } | 842 | } |
751 | 843 | ||
752 | ipath_stats.sps_ints++; | ||
753 | |||
754 | /* | ||
755 | * this needs to be flags&initted, not statusp, so we keep | ||
756 | * taking interrupts even after link goes down, etc. | ||
757 | * Also, we *must* clear the interrupt at some point, or we won't | ||
758 | * take it again, which can be real bad for errors, etc... | ||
759 | */ | ||
760 | |||
761 | if (!(dd->ipath_flags & IPATH_INITTED)) { | ||
762 | ipath_bad_intr(dd, &unexpected); | ||
763 | ret = IRQ_NONE; | ||
764 | goto bail; | ||
765 | } | ||
766 | if (unexpected) | 844 | if (unexpected) |
767 | unexpected = 0; | 845 | unexpected = 0; |
768 | 846 | ||
769 | ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat); | 847 | if (unlikely(istat & ~infinipath_i_bitsextant)) |
770 | |||
771 | if (istat & ~infinipath_i_bitsextant) | ||
772 | ipath_dev_err(dd, | 848 | ipath_dev_err(dd, |
773 | "interrupt with unknown interrupts %x set\n", | 849 | "interrupt with unknown interrupts %x set\n", |
774 | istat & (u32) ~ infinipath_i_bitsextant); | 850 | istat & (u32) ~ infinipath_i_bitsextant); |
851 | else | ||
852 | ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat); | ||
775 | 853 | ||
776 | if (istat & INFINIPATH_I_ERROR) { | 854 | if (unlikely(istat & INFINIPATH_I_ERROR)) { |
777 | ipath_stats.sps_errints++; | 855 | ipath_stats.sps_errints++; |
778 | estat = ipath_read_kreg64(dd, | 856 | estat = ipath_read_kreg64(dd, |
779 | dd->ipath_kregs->kr_errorstatus); | 857 | dd->ipath_kregs->kr_errorstatus); |
@@ -788,10 +866,18 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
788 | ipath_dev_err(dd, "Read of error status failed " | 866 | ipath_dev_err(dd, "Read of error status failed " |
789 | "(all bits set); ignoring\n"); | 867 | "(all bits set); ignoring\n"); |
790 | else | 868 | else |
791 | handle_errors(dd, estat); | 869 | if (handle_errors(dd, estat)) |
870 | /* force calling ipath_kreceive() */ | ||
871 | chk0rcv = 1; | ||
792 | } | 872 | } |
793 | 873 | ||
794 | if (istat & INFINIPATH_I_GPIO) { | 874 | if (istat & INFINIPATH_I_GPIO) { |
875 | /* | ||
876 | * Packets are available in the port 0 rcv queue. | ||
877 | * Eventually this needs to be generalized to check | ||
878 | * IPATH_GPIO_INTR, and the specific GPIO bit, if | ||
879 | * GPIO interrupts are used for anything else. | ||
880 | */ | ||
795 | if (unlikely(!(dd->ipath_flags & IPATH_GPIO_INTR))) { | 881 | if (unlikely(!(dd->ipath_flags & IPATH_GPIO_INTR))) { |
796 | u32 gpiostatus; | 882 | u32 gpiostatus; |
797 | gpiostatus = ipath_read_kreg32( | 883 | gpiostatus = ipath_read_kreg32( |
@@ -804,27 +890,39 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
804 | else { | 890 | else { |
805 | /* Clear GPIO status bit 2 */ | 891 | /* Clear GPIO status bit 2 */ |
806 | ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, | 892 | ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, |
807 | (u64) (1 << 2)); | 893 | (u64) (1 << 2)); |
808 | 894 | chk0rcv = 1; | |
809 | /* | ||
810 | * Packets are available in the port 0 rcv queue. | ||
811 | * Eventually this needs to be generalized to check | ||
812 | * IPATH_GPIO_INTR, and the specific GPIO bit, if | ||
813 | * GPIO interrupts are used for anything else. | ||
814 | */ | ||
815 | ipath_kreceive(dd); | ||
816 | } | 895 | } |
817 | } | 896 | } |
897 | chk0rcv |= istat & port0rbits; | ||
818 | 898 | ||
819 | /* | 899 | /* |
820 | * clear the ones we will deal with on this round | 900 | * Clear the interrupt bits we found set, unless they are receive |
821 | * We clear it early, mostly for receive interrupts, so we | 901 | * related, in which case we already cleared them above, and don't |
822 | * know the chip will have seen this by the time we process | 902 | * want to clear them again, because we might lose an interrupt. |
823 | * the queue, and will re-interrupt if necessary. The processor | 903 | * Clear it early, so we "know" know the chip will have seen this by |
824 | * itself won't take the interrupt again until we return. | 904 | * the time we process the queue, and will re-interrupt if necessary. |
905 | * The processor itself won't take the interrupt again until we return. | ||
825 | */ | 906 | */ |
826 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat); | 907 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat); |
827 | 908 | ||
909 | /* | ||
910 | * handle port0 receive before checking for pio buffers available, | ||
911 | * since receives can overflow; piobuf waiters can afford a few | ||
912 | * extra cycles, since they were waiting anyway, and user's waiting | ||
913 | * for receive are at the bottom. | ||
914 | */ | ||
915 | if (chk0rcv) { | ||
916 | ipath_kreceive(dd); | ||
917 | istat &= ~port0rbits; | ||
918 | } | ||
919 | |||
920 | if (istat & ((infinipath_i_rcvavail_mask << | ||
921 | INFINIPATH_I_RCVAVAIL_SHIFT) | ||
922 | | (infinipath_i_rcvurg_mask << | ||
923 | INFINIPATH_I_RCVURG_SHIFT))) | ||
924 | handle_urcv(dd, istat); | ||
925 | |||
828 | if (istat & INFINIPATH_I_SPIOBUFAVAIL) { | 926 | if (istat & INFINIPATH_I_SPIOBUFAVAIL) { |
829 | clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); | 927 | clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); |
830 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | 928 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, |
@@ -836,17 +934,7 @@ irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs) | |||
836 | handle_layer_pioavail(dd); | 934 | handle_layer_pioavail(dd); |
837 | } | 935 | } |
838 | 936 | ||
839 | /* | 937 | done: |
840 | * we check for both transition from empty to non-empty, and urgent | ||
841 | * packets (those with the interrupt bit set in the header) | ||
842 | */ | ||
843 | |||
844 | if (istat & ((infinipath_i_rcvavail_mask << | ||
845 | INFINIPATH_I_RCVAVAIL_SHIFT) | ||
846 | | (infinipath_i_rcvurg_mask << | ||
847 | INFINIPATH_I_RCVURG_SHIFT))) | ||
848 | handle_rcv(dd, istat); | ||
849 | |||
850 | ret = IRQ_HANDLED; | 938 | ret = IRQ_HANDLED; |
851 | 939 | ||
852 | bail: | 940 | bail: |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 5d92d57b6f54..e9f374fb641e 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _IPATH_KERNEL_H | 1 | #ifndef _IPATH_KERNEL_H |
2 | #define _IPATH_KERNEL_H | 2 | #define _IPATH_KERNEL_H |
3 | /* | 3 | /* |
4 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 5 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
5 | * | 6 | * |
6 | * This software is available to you under a choice of one of two | 7 | * This software is available to you under a choice of one of two |
@@ -61,9 +62,7 @@ struct ipath_portdata { | |||
61 | /* rcvhdrq base, needs mmap before useful */ | 62 | /* rcvhdrq base, needs mmap before useful */ |
62 | void *port_rcvhdrq; | 63 | void *port_rcvhdrq; |
63 | /* kernel virtual address where hdrqtail is updated */ | 64 | /* kernel virtual address where hdrqtail is updated */ |
64 | u64 *port_rcvhdrtail_kvaddr; | 65 | volatile __le64 *port_rcvhdrtail_kvaddr; |
65 | /* page * used for uaddr */ | ||
66 | struct page *port_rcvhdrtail_pagep; | ||
67 | /* | 66 | /* |
68 | * temp buffer for expected send setup, allocated at open, instead | 67 | * temp buffer for expected send setup, allocated at open, instead |
69 | * of each setup call | 68 | * of each setup call |
@@ -78,11 +77,7 @@ struct ipath_portdata { | |||
78 | dma_addr_t port_rcvegr_phys; | 77 | dma_addr_t port_rcvegr_phys; |
79 | /* mmap of hdrq, must fit in 44 bits */ | 78 | /* mmap of hdrq, must fit in 44 bits */ |
80 | dma_addr_t port_rcvhdrq_phys; | 79 | dma_addr_t port_rcvhdrq_phys; |
81 | /* | 80 | dma_addr_t port_rcvhdrqtailaddr_phys; |
82 | * the actual user address that we ipath_mlock'ed, so we can | ||
83 | * ipath_munlock it at close | ||
84 | */ | ||
85 | unsigned long port_rcvhdrtail_uaddr; | ||
86 | /* | 81 | /* |
87 | * number of opens on this instance (0 or 1; ignoring forks, dup, | 82 | * number of opens on this instance (0 or 1; ignoring forks, dup, |
88 | * etc. for now) | 83 | * etc. for now) |
@@ -158,16 +153,10 @@ struct ipath_devdata { | |||
158 | /* base of memory alloced for ipath_kregbase, for free */ | 153 | /* base of memory alloced for ipath_kregbase, for free */ |
159 | u64 *ipath_kregalloc; | 154 | u64 *ipath_kregalloc; |
160 | /* | 155 | /* |
161 | * version of kregbase that doesn't have high bits set (for 32 bit | ||
162 | * programs, so mmap64 44 bit works) | ||
163 | */ | ||
164 | u64 __iomem *ipath_kregvirt; | ||
165 | /* | ||
166 | * virtual address where port0 rcvhdrqtail updated for this unit. | 156 | * virtual address where port0 rcvhdrqtail updated for this unit. |
167 | * only written to by the chip, not the driver. | 157 | * only written to by the chip, not the driver. |
168 | */ | 158 | */ |
169 | volatile __le64 *ipath_hdrqtailptr; | 159 | volatile __le64 *ipath_hdrqtailptr; |
170 | dma_addr_t ipath_dma_addr; | ||
171 | /* ipath_cfgports pointers */ | 160 | /* ipath_cfgports pointers */ |
172 | struct ipath_portdata **ipath_pd; | 161 | struct ipath_portdata **ipath_pd; |
173 | /* sk_buffs used by port 0 eager receive queue */ | 162 | /* sk_buffs used by port 0 eager receive queue */ |
@@ -354,13 +343,17 @@ struct ipath_devdata { | |||
354 | char *ipath_freezemsg; | 343 | char *ipath_freezemsg; |
355 | /* pci access data structure */ | 344 | /* pci access data structure */ |
356 | struct pci_dev *pcidev; | 345 | struct pci_dev *pcidev; |
357 | struct cdev *cdev; | 346 | struct cdev *user_cdev; |
358 | struct class_device *class_dev; | 347 | struct cdev *diag_cdev; |
348 | struct class_device *user_class_dev; | ||
349 | struct class_device *diag_class_dev; | ||
359 | /* timer used to prevent stats overflow, error throttling, etc. */ | 350 | /* timer used to prevent stats overflow, error throttling, etc. */ |
360 | struct timer_list ipath_stats_timer; | 351 | struct timer_list ipath_stats_timer; |
361 | /* check for stale messages in rcv queue */ | 352 | /* check for stale messages in rcv queue */ |
362 | /* only allow one intr at a time. */ | 353 | /* only allow one intr at a time. */ |
363 | unsigned long ipath_rcv_pending; | 354 | unsigned long ipath_rcv_pending; |
355 | void *ipath_dummy_hdrq; /* used after port close */ | ||
356 | dma_addr_t ipath_dummy_hdrq_phys; | ||
364 | 357 | ||
365 | /* | 358 | /* |
366 | * Shadow copies of registers; size indicates read access size. | 359 | * Shadow copies of registers; size indicates read access size. |
@@ -500,8 +493,11 @@ struct ipath_devdata { | |||
500 | u16 ipath_lid; | 493 | u16 ipath_lid; |
501 | /* list of pkeys programmed; 0 if not set */ | 494 | /* list of pkeys programmed; 0 if not set */ |
502 | u16 ipath_pkeys[4]; | 495 | u16 ipath_pkeys[4]; |
503 | /* ASCII serial number, from flash */ | 496 | /* |
504 | u8 ipath_serial[12]; | 497 | * ASCII serial number, from flash, large enough for original |
498 | * all digit strings, and longer QLogic serial number format | ||
499 | */ | ||
500 | u8 ipath_serial[16]; | ||
505 | /* human readable board version */ | 501 | /* human readable board version */ |
506 | u8 ipath_boardversion[80]; | 502 | u8 ipath_boardversion[80]; |
507 | /* chip major rev, from ipath_revision */ | 503 | /* chip major rev, from ipath_revision */ |
@@ -516,12 +512,12 @@ struct ipath_devdata { | |||
516 | u8 ipath_pci_cacheline; | 512 | u8 ipath_pci_cacheline; |
517 | /* LID mask control */ | 513 | /* LID mask control */ |
518 | u8 ipath_lmc; | 514 | u8 ipath_lmc; |
519 | }; | ||
520 | |||
521 | extern volatile __le64 *ipath_port0_rcvhdrtail; | ||
522 | extern dma_addr_t ipath_port0_rcvhdrtail_dma; | ||
523 | 515 | ||
524 | #define IPATH_PORT0_RCVHDRTAIL_SIZE PAGE_SIZE | 516 | /* local link integrity counter */ |
517 | u32 ipath_lli_counter; | ||
518 | /* local link integrity errors */ | ||
519 | u32 ipath_lli_errors; | ||
520 | }; | ||
525 | 521 | ||
526 | extern struct list_head ipath_dev_list; | 522 | extern struct list_head ipath_dev_list; |
527 | extern spinlock_t ipath_devs_lock; | 523 | extern spinlock_t ipath_devs_lock; |
@@ -537,7 +533,7 @@ extern int __ipath_verbs_piobufavail(struct ipath_devdata *); | |||
537 | extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32); | 533 | extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32); |
538 | 534 | ||
539 | void ipath_layer_add(struct ipath_devdata *); | 535 | void ipath_layer_add(struct ipath_devdata *); |
540 | void ipath_layer_del(struct ipath_devdata *); | 536 | void ipath_layer_remove(struct ipath_devdata *); |
541 | 537 | ||
542 | int ipath_init_chip(struct ipath_devdata *, int); | 538 | int ipath_init_chip(struct ipath_devdata *, int); |
543 | int ipath_enable_wc(struct ipath_devdata *dd); | 539 | int ipath_enable_wc(struct ipath_devdata *dd); |
@@ -551,14 +547,14 @@ int ipath_cdev_init(int minor, char *name, struct file_operations *fops, | |||
551 | void ipath_cdev_cleanup(struct cdev **cdevp, | 547 | void ipath_cdev_cleanup(struct cdev **cdevp, |
552 | struct class_device **class_devp); | 548 | struct class_device **class_devp); |
553 | 549 | ||
554 | int ipath_diag_init(void); | 550 | int ipath_diag_add(struct ipath_devdata *); |
555 | void ipath_diag_cleanup(void); | 551 | void ipath_diag_remove(struct ipath_devdata *); |
556 | void ipath_diag_bringup_link(struct ipath_devdata *); | 552 | void ipath_diag_bringup_link(struct ipath_devdata *); |
557 | 553 | ||
558 | extern wait_queue_head_t ipath_sma_state_wait; | 554 | extern wait_queue_head_t ipath_sma_state_wait; |
559 | 555 | ||
560 | int ipath_user_add(struct ipath_devdata *dd); | 556 | int ipath_user_add(struct ipath_devdata *dd); |
561 | void ipath_user_del(struct ipath_devdata *dd); | 557 | void ipath_user_remove(struct ipath_devdata *dd); |
562 | 558 | ||
563 | struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t); | 559 | struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t); |
564 | 560 | ||
@@ -582,7 +578,7 @@ void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first, | |||
582 | unsigned cnt); | 578 | unsigned cnt); |
583 | 579 | ||
584 | int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *); | 580 | int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *); |
585 | void ipath_free_pddata(struct ipath_devdata *, u32, int); | 581 | void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *); |
586 | 582 | ||
587 | int ipath_parse_ushort(const char *str, unsigned short *valp); | 583 | int ipath_parse_ushort(const char *str, unsigned short *valp); |
588 | 584 | ||
@@ -720,13 +716,8 @@ u64 ipath_read_kreg64_port(const struct ipath_devdata *, ipath_kreg, | |||
720 | * @port: port number | 716 | * @port: port number |
721 | * | 717 | * |
722 | * Return the contents of a register that is virtualized to be per port. | 718 | * Return the contents of a register that is virtualized to be per port. |
723 | * Prints a debug message and returns -1 on errors (not distinguishable from | 719 | * Returns -1 on errors (not distinguishable from valid contents at |
724 | * valid contents at runtime; we may add a separate error variable at some | 720 | * runtime; we may add a separate error variable at some point). |
725 | * point). | ||
726 | * | ||
727 | * This is normally not used by the kernel, but may be for debugging, and | ||
728 | * has a different implementation than user mode, which is why it's not in | ||
729 | * _common.h. | ||
730 | */ | 721 | */ |
731 | static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd, | 722 | static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd, |
732 | ipath_ureg regno, int port) | 723 | ipath_ureg regno, int port) |
@@ -842,9 +833,10 @@ extern struct mutex ipath_mutex; | |||
842 | 833 | ||
843 | #define IPATH_DRV_NAME "ipath_core" | 834 | #define IPATH_DRV_NAME "ipath_core" |
844 | #define IPATH_MAJOR 233 | 835 | #define IPATH_MAJOR 233 |
836 | #define IPATH_USER_MINOR_BASE 0 | ||
845 | #define IPATH_SMA_MINOR 128 | 837 | #define IPATH_SMA_MINOR 128 |
846 | #define IPATH_DIAG_MINOR 129 | 838 | #define IPATH_DIAG_MINOR_BASE 129 |
847 | #define IPATH_NMINORS 130 | 839 | #define IPATH_NMINORS 255 |
848 | 840 | ||
849 | #define ipath_dev_err(dd,fmt,...) \ | 841 | #define ipath_dev_err(dd,fmt,...) \ |
850 | do { \ | 842 | do { \ |
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c index 5ae8761f9dd2..46773c673a1a 100644 --- a/drivers/infiniband/hw/ipath/ipath_keys.c +++ b/drivers/infiniband/hw/ipath/ipath_keys.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -120,6 +121,7 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge, | |||
120 | struct ib_sge *sge, int acc) | 121 | struct ib_sge *sge, int acc) |
121 | { | 122 | { |
122 | struct ipath_mregion *mr; | 123 | struct ipath_mregion *mr; |
124 | unsigned n, m; | ||
123 | size_t off; | 125 | size_t off; |
124 | int ret; | 126 | int ret; |
125 | 127 | ||
@@ -151,20 +153,22 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge, | |||
151 | } | 153 | } |
152 | 154 | ||
153 | off += mr->offset; | 155 | off += mr->offset; |
154 | isge->mr = mr; | 156 | m = 0; |
155 | isge->m = 0; | 157 | n = 0; |
156 | isge->n = 0; | 158 | while (off >= mr->map[m]->segs[n].length) { |
157 | while (off >= mr->map[isge->m]->segs[isge->n].length) { | 159 | off -= mr->map[m]->segs[n].length; |
158 | off -= mr->map[isge->m]->segs[isge->n].length; | 160 | n++; |
159 | isge->n++; | 161 | if (n >= IPATH_SEGSZ) { |
160 | if (isge->n >= IPATH_SEGSZ) { | 162 | m++; |
161 | isge->m++; | 163 | n = 0; |
162 | isge->n = 0; | ||
163 | } | 164 | } |
164 | } | 165 | } |
165 | isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off; | 166 | isge->mr = mr; |
166 | isge->length = mr->map[isge->m]->segs[isge->n].length - off; | 167 | isge->vaddr = mr->map[m]->segs[n].vaddr + off; |
168 | isge->length = mr->map[m]->segs[n].length - off; | ||
167 | isge->sge_length = sge->length; | 169 | isge->sge_length = sge->length; |
170 | isge->m = m; | ||
171 | isge->n = n; | ||
168 | 172 | ||
169 | ret = 1; | 173 | ret = 1; |
170 | 174 | ||
@@ -189,6 +193,7 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, | |||
189 | struct ipath_lkey_table *rkt = &dev->lk_table; | 193 | struct ipath_lkey_table *rkt = &dev->lk_table; |
190 | struct ipath_sge *sge = &ss->sge; | 194 | struct ipath_sge *sge = &ss->sge; |
191 | struct ipath_mregion *mr; | 195 | struct ipath_mregion *mr; |
196 | unsigned n, m; | ||
192 | size_t off; | 197 | size_t off; |
193 | int ret; | 198 | int ret; |
194 | 199 | ||
@@ -206,20 +211,22 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, | |||
206 | } | 211 | } |
207 | 212 | ||
208 | off += mr->offset; | 213 | off += mr->offset; |
209 | sge->mr = mr; | 214 | m = 0; |
210 | sge->m = 0; | 215 | n = 0; |
211 | sge->n = 0; | 216 | while (off >= mr->map[m]->segs[n].length) { |
212 | while (off >= mr->map[sge->m]->segs[sge->n].length) { | 217 | off -= mr->map[m]->segs[n].length; |
213 | off -= mr->map[sge->m]->segs[sge->n].length; | 218 | n++; |
214 | sge->n++; | 219 | if (n >= IPATH_SEGSZ) { |
215 | if (sge->n >= IPATH_SEGSZ) { | 220 | m++; |
216 | sge->m++; | 221 | n = 0; |
217 | sge->n = 0; | ||
218 | } | 222 | } |
219 | } | 223 | } |
220 | sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off; | 224 | sge->mr = mr; |
221 | sge->length = mr->map[sge->m]->segs[sge->n].length - off; | 225 | sge->vaddr = mr->map[m]->segs[n].vaddr + off; |
226 | sge->length = mr->map[m]->segs[n].length - off; | ||
222 | sge->sge_length = len; | 227 | sge->sge_length = len; |
228 | sge->m = m; | ||
229 | sge->n = n; | ||
223 | ss->sg_list = NULL; | 230 | ss->sg_list = NULL; |
224 | ss->num_sge = 1; | 231 | ss->num_sge = 1; |
225 | 232 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c index 9ec4ac77b87f..b28c6f81c731 100644 --- a/drivers/infiniband/hw/ipath/ipath_layer.c +++ b/drivers/infiniband/hw/ipath/ipath_layer.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -40,8 +41,8 @@ | |||
40 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
41 | 42 | ||
42 | #include "ipath_kernel.h" | 43 | #include "ipath_kernel.h" |
43 | #include "ips_common.h" | ||
44 | #include "ipath_layer.h" | 44 | #include "ipath_layer.h" |
45 | #include "ipath_common.h" | ||
45 | 46 | ||
46 | /* Acquire before ipath_devs_lock. */ | 47 | /* Acquire before ipath_devs_lock. */ |
47 | static DEFINE_MUTEX(ipath_layer_mutex); | 48 | static DEFINE_MUTEX(ipath_layer_mutex); |
@@ -299,9 +300,8 @@ bail: | |||
299 | 300 | ||
300 | EXPORT_SYMBOL_GPL(ipath_layer_set_mtu); | 301 | EXPORT_SYMBOL_GPL(ipath_layer_set_mtu); |
301 | 302 | ||
302 | int ipath_set_sps_lid(struct ipath_devdata *dd, u32 arg, u8 lmc) | 303 | int ipath_set_lid(struct ipath_devdata *dd, u32 arg, u8 lmc) |
303 | { | 304 | { |
304 | ipath_stats.sps_lid[dd->ipath_unit] = arg; | ||
305 | dd->ipath_lid = arg; | 305 | dd->ipath_lid = arg; |
306 | dd->ipath_lmc = lmc; | 306 | dd->ipath_lmc = lmc; |
307 | 307 | ||
@@ -315,7 +315,7 @@ int ipath_set_sps_lid(struct ipath_devdata *dd, u32 arg, u8 lmc) | |||
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
318 | EXPORT_SYMBOL_GPL(ipath_set_sps_lid); | 318 | EXPORT_SYMBOL_GPL(ipath_set_lid); |
319 | 319 | ||
320 | int ipath_layer_set_guid(struct ipath_devdata *dd, __be64 guid) | 320 | int ipath_layer_set_guid(struct ipath_devdata *dd, __be64 guid) |
321 | { | 321 | { |
@@ -340,18 +340,26 @@ u32 ipath_layer_get_nguid(struct ipath_devdata *dd) | |||
340 | 340 | ||
341 | EXPORT_SYMBOL_GPL(ipath_layer_get_nguid); | 341 | EXPORT_SYMBOL_GPL(ipath_layer_get_nguid); |
342 | 342 | ||
343 | int ipath_layer_query_device(struct ipath_devdata *dd, u32 * vendor, | 343 | u32 ipath_layer_get_majrev(struct ipath_devdata *dd) |
344 | u32 * boardrev, u32 * majrev, u32 * minrev) | ||
345 | { | 344 | { |
346 | *vendor = dd->ipath_vendorid; | 345 | return dd->ipath_majrev; |
347 | *boardrev = dd->ipath_boardrev; | 346 | } |
348 | *majrev = dd->ipath_majrev; | ||
349 | *minrev = dd->ipath_minrev; | ||
350 | 347 | ||
351 | return 0; | 348 | EXPORT_SYMBOL_GPL(ipath_layer_get_majrev); |
349 | |||
350 | u32 ipath_layer_get_minrev(struct ipath_devdata *dd) | ||
351 | { | ||
352 | return dd->ipath_minrev; | ||
353 | } | ||
354 | |||
355 | EXPORT_SYMBOL_GPL(ipath_layer_get_minrev); | ||
356 | |||
357 | u32 ipath_layer_get_pcirev(struct ipath_devdata *dd) | ||
358 | { | ||
359 | return dd->ipath_pcirev; | ||
352 | } | 360 | } |
353 | 361 | ||
354 | EXPORT_SYMBOL_GPL(ipath_layer_query_device); | 362 | EXPORT_SYMBOL_GPL(ipath_layer_get_pcirev); |
355 | 363 | ||
356 | u32 ipath_layer_get_flags(struct ipath_devdata *dd) | 364 | u32 ipath_layer_get_flags(struct ipath_devdata *dd) |
357 | { | 365 | { |
@@ -374,6 +382,13 @@ u16 ipath_layer_get_deviceid(struct ipath_devdata *dd) | |||
374 | 382 | ||
375 | EXPORT_SYMBOL_GPL(ipath_layer_get_deviceid); | 383 | EXPORT_SYMBOL_GPL(ipath_layer_get_deviceid); |
376 | 384 | ||
385 | u32 ipath_layer_get_vendorid(struct ipath_devdata *dd) | ||
386 | { | ||
387 | return dd->ipath_vendorid; | ||
388 | } | ||
389 | |||
390 | EXPORT_SYMBOL_GPL(ipath_layer_get_vendorid); | ||
391 | |||
377 | u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd) | 392 | u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd) |
378 | { | 393 | { |
379 | return dd->ipath_lastibcstat; | 394 | return dd->ipath_lastibcstat; |
@@ -403,7 +418,7 @@ void ipath_layer_add(struct ipath_devdata *dd) | |||
403 | mutex_unlock(&ipath_layer_mutex); | 418 | mutex_unlock(&ipath_layer_mutex); |
404 | } | 419 | } |
405 | 420 | ||
406 | void ipath_layer_del(struct ipath_devdata *dd) | 421 | void ipath_layer_remove(struct ipath_devdata *dd) |
407 | { | 422 | { |
408 | mutex_lock(&ipath_layer_mutex); | 423 | mutex_lock(&ipath_layer_mutex); |
409 | 424 | ||
@@ -607,7 +622,7 @@ int ipath_layer_open(struct ipath_devdata *dd, u32 * pktmax) | |||
607 | goto bail; | 622 | goto bail; |
608 | } | 623 | } |
609 | 624 | ||
610 | ret = ipath_setrcvhdrsize(dd, NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE); | 625 | ret = ipath_setrcvhdrsize(dd, IPATH_HEADER_QUEUE_WORDS); |
611 | 626 | ||
612 | if (ret < 0) | 627 | if (ret < 0) |
613 | goto bail; | 628 | goto bail; |
@@ -616,9 +631,9 @@ int ipath_layer_open(struct ipath_devdata *dd, u32 * pktmax) | |||
616 | 631 | ||
617 | if (*dd->ipath_statusp & IPATH_STATUS_IB_READY) | 632 | if (*dd->ipath_statusp & IPATH_STATUS_IB_READY) |
618 | intval |= IPATH_LAYER_INT_IF_UP; | 633 | intval |= IPATH_LAYER_INT_IF_UP; |
619 | if (ipath_stats.sps_lid[dd->ipath_unit]) | 634 | if (dd->ipath_lid) |
620 | intval |= IPATH_LAYER_INT_LID; | 635 | intval |= IPATH_LAYER_INT_LID; |
621 | if (ipath_stats.sps_mlid[dd->ipath_unit]) | 636 | if (dd->ipath_mlid) |
622 | intval |= IPATH_LAYER_INT_BCAST; | 637 | intval |= IPATH_LAYER_INT_BCAST; |
623 | /* | 638 | /* |
624 | * do this on open, in case low level is already up and | 639 | * do this on open, in case low level is already up and |
@@ -884,7 +899,7 @@ static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss, | |||
884 | /** | 899 | /** |
885 | * ipath_verbs_send - send a packet from the verbs layer | 900 | * ipath_verbs_send - send a packet from the verbs layer |
886 | * @dd: the infinipath device | 901 | * @dd: the infinipath device |
887 | * @hdrwords: the number of works in the header | 902 | * @hdrwords: the number of words in the header |
888 | * @hdr: the packet header | 903 | * @hdr: the packet header |
889 | * @len: the length of the packet in bytes | 904 | * @len: the length of the packet in bytes |
890 | * @ss: the SGE to send | 905 | * @ss: the SGE to send |
@@ -1016,19 +1031,22 @@ int ipath_layer_get_counters(struct ipath_devdata *dd, | |||
1016 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_ibsymbolerrcnt); | 1031 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_ibsymbolerrcnt); |
1017 | cntrs->link_error_recovery_counter = | 1032 | cntrs->link_error_recovery_counter = |
1018 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt); | 1033 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt); |
1034 | /* | ||
1035 | * The link downed counter counts when the other side downs the | ||
1036 | * connection. We add in the number of times we downed the link | ||
1037 | * due to local link integrity errors to compensate. | ||
1038 | */ | ||
1019 | cntrs->link_downed_counter = | 1039 | cntrs->link_downed_counter = |
1020 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkdowncnt); | 1040 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkdowncnt); |
1021 | cntrs->port_rcv_errors = | 1041 | cntrs->port_rcv_errors = |
1022 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_rxdroppktcnt) + | 1042 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_rxdroppktcnt) + |
1023 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvovflcnt) + | 1043 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvovflcnt) + |
1024 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_portovflcnt) + | 1044 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_portovflcnt) + |
1025 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_errrcvflowctrlcnt) + | ||
1026 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_err_rlencnt) + | 1045 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_err_rlencnt) + |
1027 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_invalidrlencnt) + | 1046 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_invalidrlencnt) + |
1028 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) + | 1047 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) + |
1029 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) + | 1048 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) + |
1030 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) + | 1049 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) + |
1031 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlinkcnt) + | ||
1032 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt); | 1050 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt); |
1033 | cntrs->port_rcv_remphys_errors = | 1051 | cntrs->port_rcv_remphys_errors = |
1034 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt); | 1052 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt); |
@@ -1042,6 +1060,8 @@ int ipath_layer_get_counters(struct ipath_devdata *dd, | |||
1042 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); | 1060 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); |
1043 | cntrs->port_rcv_packets = | 1061 | cntrs->port_rcv_packets = |
1044 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); | 1062 | ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); |
1063 | cntrs->local_link_integrity_errors = dd->ipath_lli_errors; | ||
1064 | cntrs->excessive_buffer_overrun_errors = 0; /* XXX */ | ||
1045 | 1065 | ||
1046 | ret = 0; | 1066 | ret = 0; |
1047 | 1067 | ||
@@ -1086,10 +1106,10 @@ int ipath_layer_send_hdr(struct ipath_devdata *dd, struct ether_header *hdr) | |||
1086 | } | 1106 | } |
1087 | 1107 | ||
1088 | vlsllnh = *((__be16 *) hdr); | 1108 | vlsllnh = *((__be16 *) hdr); |
1089 | if (vlsllnh != htons(IPS_LRH_BTH)) { | 1109 | if (vlsllnh != htons(IPATH_LRH_BTH)) { |
1090 | ipath_dbg("Warning: lrh[0] wrong (%x, not %x); " | 1110 | ipath_dbg("Warning: lrh[0] wrong (%x, not %x); " |
1091 | "not sending\n", be16_to_cpu(vlsllnh), | 1111 | "not sending\n", be16_to_cpu(vlsllnh), |
1092 | IPS_LRH_BTH); | 1112 | IPATH_LRH_BTH); |
1093 | ret = -EINVAL; | 1113 | ret = -EINVAL; |
1094 | } | 1114 | } |
1095 | if (ret) | 1115 | if (ret) |
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.h b/drivers/infiniband/hw/ipath/ipath_layer.h index 6fefd15bd2da..71485096fcac 100644 --- a/drivers/infiniband/hw/ipath/ipath_layer.h +++ b/drivers/infiniband/hw/ipath/ipath_layer.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -54,6 +55,8 @@ struct ipath_layer_counters { | |||
54 | u64 port_rcv_data; | 55 | u64 port_rcv_data; |
55 | u64 port_xmit_packets; | 56 | u64 port_xmit_packets; |
56 | u64 port_rcv_packets; | 57 | u64 port_rcv_packets; |
58 | u32 local_link_integrity_errors; | ||
59 | u32 excessive_buffer_overrun_errors; | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | /* | 62 | /* |
@@ -126,7 +129,7 @@ u16 ipath_layer_get_bcast(struct ipath_devdata *dd); | |||
126 | u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd); | 129 | u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd); |
127 | int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 state); | 130 | int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 state); |
128 | int ipath_layer_set_mtu(struct ipath_devdata *, u16); | 131 | int ipath_layer_set_mtu(struct ipath_devdata *, u16); |
129 | int ipath_set_sps_lid(struct ipath_devdata *, u32, u8); | 132 | int ipath_set_lid(struct ipath_devdata *, u32, u8); |
130 | int ipath_layer_send_hdr(struct ipath_devdata *dd, | 133 | int ipath_layer_send_hdr(struct ipath_devdata *dd, |
131 | struct ether_header *hdr); | 134 | struct ether_header *hdr); |
132 | int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, | 135 | int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, |
@@ -143,11 +146,13 @@ int ipath_layer_want_buffer(struct ipath_devdata *dd); | |||
143 | int ipath_layer_set_guid(struct ipath_devdata *, __be64 guid); | 146 | int ipath_layer_set_guid(struct ipath_devdata *, __be64 guid); |
144 | __be64 ipath_layer_get_guid(struct ipath_devdata *); | 147 | __be64 ipath_layer_get_guid(struct ipath_devdata *); |
145 | u32 ipath_layer_get_nguid(struct ipath_devdata *); | 148 | u32 ipath_layer_get_nguid(struct ipath_devdata *); |
146 | int ipath_layer_query_device(struct ipath_devdata *, u32 * vendor, | 149 | u32 ipath_layer_get_majrev(struct ipath_devdata *); |
147 | u32 * boardrev, u32 * majrev, u32 * minrev); | 150 | u32 ipath_layer_get_minrev(struct ipath_devdata *); |
151 | u32 ipath_layer_get_pcirev(struct ipath_devdata *); | ||
148 | u32 ipath_layer_get_flags(struct ipath_devdata *dd); | 152 | u32 ipath_layer_get_flags(struct ipath_devdata *dd); |
149 | struct device *ipath_layer_get_device(struct ipath_devdata *dd); | 153 | struct device *ipath_layer_get_device(struct ipath_devdata *dd); |
150 | u16 ipath_layer_get_deviceid(struct ipath_devdata *dd); | 154 | u16 ipath_layer_get_deviceid(struct ipath_devdata *dd); |
155 | u32 ipath_layer_get_vendorid(struct ipath_devdata *); | ||
151 | u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd); | 156 | u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd); |
152 | u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd); | 157 | u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd); |
153 | int ipath_layer_enable_timer(struct ipath_devdata *dd); | 158 | int ipath_layer_enable_timer(struct ipath_devdata *dd); |
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index 1a9d0a2c33c3..d3402341b7d0 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -34,7 +35,7 @@ | |||
34 | 35 | ||
35 | #include "ipath_kernel.h" | 36 | #include "ipath_kernel.h" |
36 | #include "ipath_verbs.h" | 37 | #include "ipath_verbs.h" |
37 | #include "ips_common.h" | 38 | #include "ipath_common.h" |
38 | 39 | ||
39 | #define IB_SMP_UNSUP_VERSION __constant_htons(0x0004) | 40 | #define IB_SMP_UNSUP_VERSION __constant_htons(0x0004) |
40 | #define IB_SMP_UNSUP_METHOD __constant_htons(0x0008) | 41 | #define IB_SMP_UNSUP_METHOD __constant_htons(0x0008) |
@@ -84,7 +85,7 @@ static int recv_subn_get_nodeinfo(struct ib_smp *smp, | |||
84 | { | 85 | { |
85 | struct nodeinfo *nip = (struct nodeinfo *)&smp->data; | 86 | struct nodeinfo *nip = (struct nodeinfo *)&smp->data; |
86 | struct ipath_devdata *dd = to_idev(ibdev)->dd; | 87 | struct ipath_devdata *dd = to_idev(ibdev)->dd; |
87 | u32 vendor, boardid, majrev, minrev; | 88 | u32 vendor, majrev, minrev; |
88 | 89 | ||
89 | if (smp->attr_mod) | 90 | if (smp->attr_mod) |
90 | smp->status |= IB_SMP_INVALID_FIELD; | 91 | smp->status |= IB_SMP_INVALID_FIELD; |
@@ -104,9 +105,11 @@ static int recv_subn_get_nodeinfo(struct ib_smp *smp, | |||
104 | nip->port_guid = nip->sys_guid; | 105 | nip->port_guid = nip->sys_guid; |
105 | nip->partition_cap = cpu_to_be16(ipath_layer_get_npkeys(dd)); | 106 | nip->partition_cap = cpu_to_be16(ipath_layer_get_npkeys(dd)); |
106 | nip->device_id = cpu_to_be16(ipath_layer_get_deviceid(dd)); | 107 | nip->device_id = cpu_to_be16(ipath_layer_get_deviceid(dd)); |
107 | ipath_layer_query_device(dd, &vendor, &boardid, &majrev, &minrev); | 108 | majrev = ipath_layer_get_majrev(dd); |
109 | minrev = ipath_layer_get_minrev(dd); | ||
108 | nip->revision = cpu_to_be32((majrev << 16) | minrev); | 110 | nip->revision = cpu_to_be32((majrev << 16) | minrev); |
109 | nip->local_port_num = port; | 111 | nip->local_port_num = port; |
112 | vendor = ipath_layer_get_vendorid(dd); | ||
110 | nip->vendor_id[0] = 0; | 113 | nip->vendor_id[0] = 0; |
111 | nip->vendor_id[1] = vendor >> 8; | 114 | nip->vendor_id[1] = vendor >> 8; |
112 | nip->vendor_id[2] = vendor; | 115 | nip->vendor_id[2] = vendor; |
@@ -215,7 +218,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, | |||
215 | /* P_KeyViolations are counted by hardware. */ | 218 | /* P_KeyViolations are counted by hardware. */ |
216 | pip->pkey_violations = | 219 | pip->pkey_violations = |
217 | cpu_to_be16((ipath_layer_get_cr_errpkey(dev->dd) - | 220 | cpu_to_be16((ipath_layer_get_cr_errpkey(dev->dd) - |
218 | dev->n_pkey_violations) & 0xFFFF); | 221 | dev->z_pkey_violations) & 0xFFFF); |
219 | pip->qkey_violations = cpu_to_be16(dev->qkey_violations); | 222 | pip->qkey_violations = cpu_to_be16(dev->qkey_violations); |
220 | /* Only the hardware GUID is supported for now */ | 223 | /* Only the hardware GUID is supported for now */ |
221 | pip->guid_cap = 1; | 224 | pip->guid_cap = 1; |
@@ -303,9 +306,9 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, | |||
303 | lid = be16_to_cpu(pip->lid); | 306 | lid = be16_to_cpu(pip->lid); |
304 | if (lid != ipath_layer_get_lid(dev->dd)) { | 307 | if (lid != ipath_layer_get_lid(dev->dd)) { |
305 | /* Must be a valid unicast LID address. */ | 308 | /* Must be a valid unicast LID address. */ |
306 | if (lid == 0 || lid >= IPS_MULTICAST_LID_BASE) | 309 | if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) |
307 | goto err; | 310 | goto err; |
308 | ipath_set_sps_lid(dev->dd, lid, pip->mkeyprot_resv_lmc & 7); | 311 | ipath_set_lid(dev->dd, lid, pip->mkeyprot_resv_lmc & 7); |
309 | event.event = IB_EVENT_LID_CHANGE; | 312 | event.event = IB_EVENT_LID_CHANGE; |
310 | ib_dispatch_event(&event); | 313 | ib_dispatch_event(&event); |
311 | } | 314 | } |
@@ -313,7 +316,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, | |||
313 | smlid = be16_to_cpu(pip->sm_lid); | 316 | smlid = be16_to_cpu(pip->sm_lid); |
314 | if (smlid != dev->sm_lid) { | 317 | if (smlid != dev->sm_lid) { |
315 | /* Must be a valid unicast LID address. */ | 318 | /* Must be a valid unicast LID address. */ |
316 | if (smlid == 0 || smlid >= IPS_MULTICAST_LID_BASE) | 319 | if (smlid == 0 || smlid >= IPATH_MULTICAST_LID_BASE) |
317 | goto err; | 320 | goto err; |
318 | dev->sm_lid = smlid; | 321 | dev->sm_lid = smlid; |
319 | event.event = IB_EVENT_SM_CHANGE; | 322 | event.event = IB_EVENT_SM_CHANGE; |
@@ -389,7 +392,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, | |||
389 | * later. | 392 | * later. |
390 | */ | 393 | */ |
391 | if (pip->pkey_violations == 0) | 394 | if (pip->pkey_violations == 0) |
392 | dev->n_pkey_violations = | 395 | dev->z_pkey_violations = |
393 | ipath_layer_get_cr_errpkey(dev->dd); | 396 | ipath_layer_get_cr_errpkey(dev->dd); |
394 | 397 | ||
395 | if (pip->qkey_violations == 0) | 398 | if (pip->qkey_violations == 0) |
@@ -610,6 +613,9 @@ struct ib_pma_portcounters { | |||
610 | #define IB_PMA_SEL_PORT_RCV_ERRORS __constant_htons(0x0008) | 613 | #define IB_PMA_SEL_PORT_RCV_ERRORS __constant_htons(0x0008) |
611 | #define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS __constant_htons(0x0010) | 614 | #define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS __constant_htons(0x0010) |
612 | #define IB_PMA_SEL_PORT_XMIT_DISCARDS __constant_htons(0x0040) | 615 | #define IB_PMA_SEL_PORT_XMIT_DISCARDS __constant_htons(0x0040) |
616 | #define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS __constant_htons(0x0200) | ||
617 | #define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS __constant_htons(0x0400) | ||
618 | #define IB_PMA_SEL_PORT_VL15_DROPPED __constant_htons(0x0800) | ||
613 | #define IB_PMA_SEL_PORT_XMIT_DATA __constant_htons(0x1000) | 619 | #define IB_PMA_SEL_PORT_XMIT_DATA __constant_htons(0x1000) |
614 | #define IB_PMA_SEL_PORT_RCV_DATA __constant_htons(0x2000) | 620 | #define IB_PMA_SEL_PORT_RCV_DATA __constant_htons(0x2000) |
615 | #define IB_PMA_SEL_PORT_XMIT_PACKETS __constant_htons(0x4000) | 621 | #define IB_PMA_SEL_PORT_XMIT_PACKETS __constant_htons(0x4000) |
@@ -844,18 +850,22 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, | |||
844 | ipath_layer_get_counters(dev->dd, &cntrs); | 850 | ipath_layer_get_counters(dev->dd, &cntrs); |
845 | 851 | ||
846 | /* Adjust counters for any resets done. */ | 852 | /* Adjust counters for any resets done. */ |
847 | cntrs.symbol_error_counter -= dev->n_symbol_error_counter; | 853 | cntrs.symbol_error_counter -= dev->z_symbol_error_counter; |
848 | cntrs.link_error_recovery_counter -= | 854 | cntrs.link_error_recovery_counter -= |
849 | dev->n_link_error_recovery_counter; | 855 | dev->z_link_error_recovery_counter; |
850 | cntrs.link_downed_counter -= dev->n_link_downed_counter; | 856 | cntrs.link_downed_counter -= dev->z_link_downed_counter; |
851 | cntrs.port_rcv_errors += dev->rcv_errors; | 857 | cntrs.port_rcv_errors += dev->rcv_errors; |
852 | cntrs.port_rcv_errors -= dev->n_port_rcv_errors; | 858 | cntrs.port_rcv_errors -= dev->z_port_rcv_errors; |
853 | cntrs.port_rcv_remphys_errors -= dev->n_port_rcv_remphys_errors; | 859 | cntrs.port_rcv_remphys_errors -= dev->z_port_rcv_remphys_errors; |
854 | cntrs.port_xmit_discards -= dev->n_port_xmit_discards; | 860 | cntrs.port_xmit_discards -= dev->z_port_xmit_discards; |
855 | cntrs.port_xmit_data -= dev->n_port_xmit_data; | 861 | cntrs.port_xmit_data -= dev->z_port_xmit_data; |
856 | cntrs.port_rcv_data -= dev->n_port_rcv_data; | 862 | cntrs.port_rcv_data -= dev->z_port_rcv_data; |
857 | cntrs.port_xmit_packets -= dev->n_port_xmit_packets; | 863 | cntrs.port_xmit_packets -= dev->z_port_xmit_packets; |
858 | cntrs.port_rcv_packets -= dev->n_port_rcv_packets; | 864 | cntrs.port_rcv_packets -= dev->z_port_rcv_packets; |
865 | cntrs.local_link_integrity_errors -= | ||
866 | dev->z_local_link_integrity_errors; | ||
867 | cntrs.excessive_buffer_overrun_errors -= | ||
868 | dev->z_excessive_buffer_overrun_errors; | ||
859 | 869 | ||
860 | memset(pmp->data, 0, sizeof(pmp->data)); | 870 | memset(pmp->data, 0, sizeof(pmp->data)); |
861 | 871 | ||
@@ -893,6 +903,16 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, | |||
893 | else | 903 | else |
894 | p->port_xmit_discards = | 904 | p->port_xmit_discards = |
895 | cpu_to_be16((u16)cntrs.port_xmit_discards); | 905 | cpu_to_be16((u16)cntrs.port_xmit_discards); |
906 | if (cntrs.local_link_integrity_errors > 0xFUL) | ||
907 | cntrs.local_link_integrity_errors = 0xFUL; | ||
908 | if (cntrs.excessive_buffer_overrun_errors > 0xFUL) | ||
909 | cntrs.excessive_buffer_overrun_errors = 0xFUL; | ||
910 | p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) | | ||
911 | cntrs.excessive_buffer_overrun_errors; | ||
912 | if (dev->n_vl15_dropped > 0xFFFFUL) | ||
913 | p->vl15_dropped = __constant_cpu_to_be16(0xFFFF); | ||
914 | else | ||
915 | p->vl15_dropped = cpu_to_be16((u16)dev->n_vl15_dropped); | ||
896 | if (cntrs.port_xmit_data > 0xFFFFFFFFUL) | 916 | if (cntrs.port_xmit_data > 0xFFFFFFFFUL) |
897 | p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF); | 917 | p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF); |
898 | else | 918 | else |
@@ -928,10 +948,10 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp, | |||
928 | &rpkts, &xwait); | 948 | &rpkts, &xwait); |
929 | 949 | ||
930 | /* Adjust counters for any resets done. */ | 950 | /* Adjust counters for any resets done. */ |
931 | swords -= dev->n_port_xmit_data; | 951 | swords -= dev->z_port_xmit_data; |
932 | rwords -= dev->n_port_rcv_data; | 952 | rwords -= dev->z_port_rcv_data; |
933 | spkts -= dev->n_port_xmit_packets; | 953 | spkts -= dev->z_port_xmit_packets; |
934 | rpkts -= dev->n_port_rcv_packets; | 954 | rpkts -= dev->z_port_rcv_packets; |
935 | 955 | ||
936 | memset(pmp->data, 0, sizeof(pmp->data)); | 956 | memset(pmp->data, 0, sizeof(pmp->data)); |
937 | 957 | ||
@@ -967,37 +987,48 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp, | |||
967 | ipath_layer_get_counters(dev->dd, &cntrs); | 987 | ipath_layer_get_counters(dev->dd, &cntrs); |
968 | 988 | ||
969 | if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR) | 989 | if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR) |
970 | dev->n_symbol_error_counter = cntrs.symbol_error_counter; | 990 | dev->z_symbol_error_counter = cntrs.symbol_error_counter; |
971 | 991 | ||
972 | if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY) | 992 | if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY) |
973 | dev->n_link_error_recovery_counter = | 993 | dev->z_link_error_recovery_counter = |
974 | cntrs.link_error_recovery_counter; | 994 | cntrs.link_error_recovery_counter; |
975 | 995 | ||
976 | if (p->counter_select & IB_PMA_SEL_LINK_DOWNED) | 996 | if (p->counter_select & IB_PMA_SEL_LINK_DOWNED) |
977 | dev->n_link_downed_counter = cntrs.link_downed_counter; | 997 | dev->z_link_downed_counter = cntrs.link_downed_counter; |
978 | 998 | ||
979 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS) | 999 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS) |
980 | dev->n_port_rcv_errors = | 1000 | dev->z_port_rcv_errors = |
981 | cntrs.port_rcv_errors + dev->rcv_errors; | 1001 | cntrs.port_rcv_errors + dev->rcv_errors; |
982 | 1002 | ||
983 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS) | 1003 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS) |
984 | dev->n_port_rcv_remphys_errors = | 1004 | dev->z_port_rcv_remphys_errors = |
985 | cntrs.port_rcv_remphys_errors; | 1005 | cntrs.port_rcv_remphys_errors; |
986 | 1006 | ||
987 | if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS) | 1007 | if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS) |
988 | dev->n_port_xmit_discards = cntrs.port_xmit_discards; | 1008 | dev->z_port_xmit_discards = cntrs.port_xmit_discards; |
1009 | |||
1010 | if (p->counter_select & IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS) | ||
1011 | dev->z_local_link_integrity_errors = | ||
1012 | cntrs.local_link_integrity_errors; | ||
1013 | |||
1014 | if (p->counter_select & IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS) | ||
1015 | dev->z_excessive_buffer_overrun_errors = | ||
1016 | cntrs.excessive_buffer_overrun_errors; | ||
1017 | |||
1018 | if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED) | ||
1019 | dev->n_vl15_dropped = 0; | ||
989 | 1020 | ||
990 | if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA) | 1021 | if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA) |
991 | dev->n_port_xmit_data = cntrs.port_xmit_data; | 1022 | dev->z_port_xmit_data = cntrs.port_xmit_data; |
992 | 1023 | ||
993 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA) | 1024 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA) |
994 | dev->n_port_rcv_data = cntrs.port_rcv_data; | 1025 | dev->z_port_rcv_data = cntrs.port_rcv_data; |
995 | 1026 | ||
996 | if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS) | 1027 | if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS) |
997 | dev->n_port_xmit_packets = cntrs.port_xmit_packets; | 1028 | dev->z_port_xmit_packets = cntrs.port_xmit_packets; |
998 | 1029 | ||
999 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS) | 1030 | if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS) |
1000 | dev->n_port_rcv_packets = cntrs.port_rcv_packets; | 1031 | dev->z_port_rcv_packets = cntrs.port_rcv_packets; |
1001 | 1032 | ||
1002 | return recv_pma_get_portcounters(pmp, ibdev, port); | 1033 | return recv_pma_get_portcounters(pmp, ibdev, port); |
1003 | } | 1034 | } |
@@ -1014,16 +1045,16 @@ static int recv_pma_set_portcounters_ext(struct ib_perf *pmp, | |||
1014 | &rpkts, &xwait); | 1045 | &rpkts, &xwait); |
1015 | 1046 | ||
1016 | if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA) | 1047 | if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA) |
1017 | dev->n_port_xmit_data = swords; | 1048 | dev->z_port_xmit_data = swords; |
1018 | 1049 | ||
1019 | if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA) | 1050 | if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA) |
1020 | dev->n_port_rcv_data = rwords; | 1051 | dev->z_port_rcv_data = rwords; |
1021 | 1052 | ||
1022 | if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS) | 1053 | if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS) |
1023 | dev->n_port_xmit_packets = spkts; | 1054 | dev->z_port_xmit_packets = spkts; |
1024 | 1055 | ||
1025 | if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS) | 1056 | if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS) |
1026 | dev->n_port_rcv_packets = rpkts; | 1057 | dev->z_port_rcv_packets = rpkts; |
1027 | 1058 | ||
1028 | if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS) | 1059 | if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS) |
1029 | dev->n_unicast_xmit = 0; | 1060 | dev->n_unicast_xmit = 0; |
@@ -1272,32 +1303,8 @@ int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
1272 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 1303 | struct ib_wc *in_wc, struct ib_grh *in_grh, |
1273 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 1304 | struct ib_mad *in_mad, struct ib_mad *out_mad) |
1274 | { | 1305 | { |
1275 | struct ipath_ibdev *dev = to_idev(ibdev); | ||
1276 | int ret; | 1306 | int ret; |
1277 | 1307 | ||
1278 | /* | ||
1279 | * Snapshot current HW counters to "clear" them. | ||
1280 | * This should be done when the driver is loaded except that for | ||
1281 | * some reason we get a zillion errors when brining up the link. | ||
1282 | */ | ||
1283 | if (dev->rcv_errors == 0) { | ||
1284 | struct ipath_layer_counters cntrs; | ||
1285 | |||
1286 | ipath_layer_get_counters(to_idev(ibdev)->dd, &cntrs); | ||
1287 | dev->rcv_errors++; | ||
1288 | dev->n_symbol_error_counter = cntrs.symbol_error_counter; | ||
1289 | dev->n_link_error_recovery_counter = | ||
1290 | cntrs.link_error_recovery_counter; | ||
1291 | dev->n_link_downed_counter = cntrs.link_downed_counter; | ||
1292 | dev->n_port_rcv_errors = cntrs.port_rcv_errors + 1; | ||
1293 | dev->n_port_rcv_remphys_errors = | ||
1294 | cntrs.port_rcv_remphys_errors; | ||
1295 | dev->n_port_xmit_discards = cntrs.port_xmit_discards; | ||
1296 | dev->n_port_xmit_data = cntrs.port_xmit_data; | ||
1297 | dev->n_port_rcv_data = cntrs.port_rcv_data; | ||
1298 | dev->n_port_xmit_packets = cntrs.port_xmit_packets; | ||
1299 | dev->n_port_rcv_packets = cntrs.port_rcv_packets; | ||
1300 | } | ||
1301 | switch (in_mad->mad_hdr.mgmt_class) { | 1308 | switch (in_mad->mad_hdr.mgmt_class) { |
1302 | case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: | 1309 | case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: |
1303 | case IB_MGMT_CLASS_SUBN_LID_ROUTED: | 1310 | case IB_MGMT_CLASS_SUBN_LID_ROUTED: |
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c index 69ffec66d45d..4ac31a5da330 100644 --- a/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/drivers/infiniband/hw/ipath/ipath_mr.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -169,6 +170,11 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, | |||
169 | int n, m, i; | 170 | int n, m, i; |
170 | struct ib_mr *ret; | 171 | struct ib_mr *ret; |
171 | 172 | ||
173 | if (region->length == 0) { | ||
174 | ret = ERR_PTR(-EINVAL); | ||
175 | goto bail; | ||
176 | } | ||
177 | |||
172 | n = 0; | 178 | n = 0; |
173 | list_for_each_entry(chunk, ®ion->chunk_list, list) | 179 | list_for_each_entry(chunk, ®ion->chunk_list, list) |
174 | n += chunk->nents; | 180 | n += chunk->nents; |
diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c index 02e8c75b24f6..b83f66d8262c 100644 --- a/drivers/infiniband/hw/ipath/ipath_pe800.c +++ b/drivers/infiniband/hw/ipath/ipath_pe800.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -44,7 +45,7 @@ | |||
44 | 45 | ||
45 | /* | 46 | /* |
46 | * This file contains all the chip-specific register information and | 47 | * This file contains all the chip-specific register information and |
47 | * access functions for the PathScale PE800, the PCI-Express chip. | 48 | * access functions for the QLogic InfiniPath PE800, the PCI-Express chip. |
48 | * | 49 | * |
49 | * This lists the InfiniPath PE800 registers, in the actual chip layout. | 50 | * This lists the InfiniPath PE800 registers, in the actual chip layout. |
50 | * This structure should never be directly accessed. | 51 | * This structure should never be directly accessed. |
@@ -532,7 +533,7 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name, | |||
532 | if (n) | 533 | if (n) |
533 | snprintf(name, namelen, "%s", n); | 534 | snprintf(name, namelen, "%s", n); |
534 | 535 | ||
535 | if (dd->ipath_majrev != 4 || dd->ipath_minrev != 1) { | 536 | if (dd->ipath_majrev != 4 || !dd->ipath_minrev || dd->ipath_minrev>2) { |
536 | ipath_dev_err(dd, "Unsupported PE-800 revision %u.%u!\n", | 537 | ipath_dev_err(dd, "Unsupported PE-800 revision %u.%u!\n", |
537 | dd->ipath_majrev, dd->ipath_minrev); | 538 | dd->ipath_majrev, dd->ipath_minrev); |
538 | ret = 1; | 539 | ret = 1; |
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 9f8855d970c8..83e557be591e 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -34,7 +35,7 @@ | |||
34 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
35 | 36 | ||
36 | #include "ipath_verbs.h" | 37 | #include "ipath_verbs.h" |
37 | #include "ips_common.h" | 38 | #include "ipath_common.h" |
38 | 39 | ||
39 | #define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE) | 40 | #define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE) |
40 | #define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1) | 41 | #define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1) |
@@ -332,10 +333,11 @@ static void ipath_reset_qp(struct ipath_qp *qp) | |||
332 | qp->remote_qpn = 0; | 333 | qp->remote_qpn = 0; |
333 | qp->qkey = 0; | 334 | qp->qkey = 0; |
334 | qp->qp_access_flags = 0; | 335 | qp->qp_access_flags = 0; |
336 | clear_bit(IPATH_S_BUSY, &qp->s_flags); | ||
335 | qp->s_hdrwords = 0; | 337 | qp->s_hdrwords = 0; |
336 | qp->s_psn = 0; | 338 | qp->s_psn = 0; |
337 | qp->r_psn = 0; | 339 | qp->r_psn = 0; |
338 | atomic_set(&qp->msn, 0); | 340 | qp->r_msn = 0; |
339 | if (qp->ibqp.qp_type == IB_QPT_RC) { | 341 | if (qp->ibqp.qp_type == IB_QPT_RC) { |
340 | qp->s_state = IB_OPCODE_RC_SEND_LAST; | 342 | qp->s_state = IB_OPCODE_RC_SEND_LAST; |
341 | qp->r_state = IB_OPCODE_RC_SEND_LAST; | 343 | qp->r_state = IB_OPCODE_RC_SEND_LAST; |
@@ -344,7 +346,8 @@ static void ipath_reset_qp(struct ipath_qp *qp) | |||
344 | qp->r_state = IB_OPCODE_UC_SEND_LAST; | 346 | qp->r_state = IB_OPCODE_UC_SEND_LAST; |
345 | } | 347 | } |
346 | qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; | 348 | qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; |
347 | qp->s_nak_state = 0; | 349 | qp->r_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; |
350 | qp->r_nak_state = 0; | ||
348 | qp->s_rnr_timeout = 0; | 351 | qp->s_rnr_timeout = 0; |
349 | qp->s_head = 0; | 352 | qp->s_head = 0; |
350 | qp->s_tail = 0; | 353 | qp->s_tail = 0; |
@@ -362,10 +365,10 @@ static void ipath_reset_qp(struct ipath_qp *qp) | |||
362 | * @qp: the QP to put into an error state | 365 | * @qp: the QP to put into an error state |
363 | * | 366 | * |
364 | * Flushes both send and receive work queues. | 367 | * Flushes both send and receive work queues. |
365 | * QP r_rq.lock and s_lock should be held. | 368 | * QP s_lock should be held and interrupts disabled. |
366 | */ | 369 | */ |
367 | 370 | ||
368 | static void ipath_error_qp(struct ipath_qp *qp) | 371 | void ipath_error_qp(struct ipath_qp *qp) |
369 | { | 372 | { |
370 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | 373 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); |
371 | struct ib_wc wc; | 374 | struct ib_wc wc; |
@@ -408,12 +411,14 @@ static void ipath_error_qp(struct ipath_qp *qp) | |||
408 | qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; | 411 | qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; |
409 | 412 | ||
410 | wc.opcode = IB_WC_RECV; | 413 | wc.opcode = IB_WC_RECV; |
414 | spin_lock(&qp->r_rq.lock); | ||
411 | while (qp->r_rq.tail != qp->r_rq.head) { | 415 | while (qp->r_rq.tail != qp->r_rq.head) { |
412 | wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id; | 416 | wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id; |
413 | if (++qp->r_rq.tail >= qp->r_rq.size) | 417 | if (++qp->r_rq.tail >= qp->r_rq.size) |
414 | qp->r_rq.tail = 0; | 418 | qp->r_rq.tail = 0; |
415 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); | 419 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); |
416 | } | 420 | } |
421 | spin_unlock(&qp->r_rq.lock); | ||
417 | } | 422 | } |
418 | 423 | ||
419 | /** | 424 | /** |
@@ -433,8 +438,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
433 | unsigned long flags; | 438 | unsigned long flags; |
434 | int ret; | 439 | int ret; |
435 | 440 | ||
436 | spin_lock_irqsave(&qp->r_rq.lock, flags); | 441 | spin_lock_irqsave(&qp->s_lock, flags); |
437 | spin_lock(&qp->s_lock); | ||
438 | 442 | ||
439 | cur_state = attr_mask & IB_QP_CUR_STATE ? | 443 | cur_state = attr_mask & IB_QP_CUR_STATE ? |
440 | attr->cur_qp_state : qp->state; | 444 | attr->cur_qp_state : qp->state; |
@@ -446,7 +450,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
446 | 450 | ||
447 | if (attr_mask & IB_QP_AV) | 451 | if (attr_mask & IB_QP_AV) |
448 | if (attr->ah_attr.dlid == 0 || | 452 | if (attr->ah_attr.dlid == 0 || |
449 | attr->ah_attr.dlid >= IPS_MULTICAST_LID_BASE) | 453 | attr->ah_attr.dlid >= IPATH_MULTICAST_LID_BASE) |
450 | goto inval; | 454 | goto inval; |
451 | 455 | ||
452 | if (attr_mask & IB_QP_PKEY_INDEX) | 456 | if (attr_mask & IB_QP_PKEY_INDEX) |
@@ -505,34 +509,19 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
505 | } | 509 | } |
506 | 510 | ||
507 | if (attr_mask & IB_QP_MIN_RNR_TIMER) | 511 | if (attr_mask & IB_QP_MIN_RNR_TIMER) |
508 | qp->s_min_rnr_timer = attr->min_rnr_timer; | 512 | qp->r_min_rnr_timer = attr->min_rnr_timer; |
509 | 513 | ||
510 | if (attr_mask & IB_QP_QKEY) | 514 | if (attr_mask & IB_QP_QKEY) |
511 | qp->qkey = attr->qkey; | 515 | qp->qkey = attr->qkey; |
512 | 516 | ||
513 | if (attr_mask & IB_QP_PKEY_INDEX) | ||
514 | qp->s_pkey_index = attr->pkey_index; | ||
515 | |||
516 | qp->state = new_state; | 517 | qp->state = new_state; |
517 | spin_unlock(&qp->s_lock); | 518 | spin_unlock_irqrestore(&qp->s_lock, flags); |
518 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
519 | |||
520 | /* | ||
521 | * If QP1 changed to the RTS state, try to move to the link to INIT | ||
522 | * even if it was ACTIVE so the SM will reinitialize the SMA's | ||
523 | * state. | ||
524 | */ | ||
525 | if (qp->ibqp.qp_num == 1 && new_state == IB_QPS_RTS) { | ||
526 | struct ipath_ibdev *dev = to_idev(ibqp->device); | ||
527 | 519 | ||
528 | ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN); | ||
529 | } | ||
530 | ret = 0; | 520 | ret = 0; |
531 | goto bail; | 521 | goto bail; |
532 | 522 | ||
533 | inval: | 523 | inval: |
534 | spin_unlock(&qp->s_lock); | 524 | spin_unlock_irqrestore(&qp->s_lock, flags); |
535 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
536 | ret = -EINVAL; | 525 | ret = -EINVAL; |
537 | 526 | ||
538 | bail: | 527 | bail: |
@@ -566,7 +555,7 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
566 | attr->sq_draining = 0; | 555 | attr->sq_draining = 0; |
567 | attr->max_rd_atomic = 1; | 556 | attr->max_rd_atomic = 1; |
568 | attr->max_dest_rd_atomic = 1; | 557 | attr->max_dest_rd_atomic = 1; |
569 | attr->min_rnr_timer = qp->s_min_rnr_timer; | 558 | attr->min_rnr_timer = qp->r_min_rnr_timer; |
570 | attr->port_num = 1; | 559 | attr->port_num = 1; |
571 | attr->timeout = 0; | 560 | attr->timeout = 0; |
572 | attr->retry_cnt = qp->s_retry_cnt; | 561 | attr->retry_cnt = qp->s_retry_cnt; |
@@ -593,21 +582,17 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
593 | * @qp: the queue pair to compute the AETH for | 582 | * @qp: the queue pair to compute the AETH for |
594 | * | 583 | * |
595 | * Returns the AETH. | 584 | * Returns the AETH. |
596 | * | ||
597 | * The QP s_lock should be held. | ||
598 | */ | 585 | */ |
599 | __be32 ipath_compute_aeth(struct ipath_qp *qp) | 586 | __be32 ipath_compute_aeth(struct ipath_qp *qp) |
600 | { | 587 | { |
601 | u32 aeth = atomic_read(&qp->msn) & IPS_MSN_MASK; | 588 | u32 aeth = qp->r_msn & IPATH_MSN_MASK; |
602 | 589 | ||
603 | if (qp->s_nak_state) { | 590 | if (qp->ibqp.srq) { |
604 | aeth |= qp->s_nak_state << IPS_AETH_CREDIT_SHIFT; | ||
605 | } else if (qp->ibqp.srq) { | ||
606 | /* | 591 | /* |
607 | * Shared receive queues don't generate credits. | 592 | * Shared receive queues don't generate credits. |
608 | * Set the credit field to the invalid value. | 593 | * Set the credit field to the invalid value. |
609 | */ | 594 | */ |
610 | aeth |= IPS_AETH_CREDIT_INVAL << IPS_AETH_CREDIT_SHIFT; | 595 | aeth |= IPATH_AETH_CREDIT_INVAL << IPATH_AETH_CREDIT_SHIFT; |
611 | } else { | 596 | } else { |
612 | u32 min, max, x; | 597 | u32 min, max, x; |
613 | u32 credits; | 598 | u32 credits; |
@@ -637,7 +622,7 @@ __be32 ipath_compute_aeth(struct ipath_qp *qp) | |||
637 | else | 622 | else |
638 | min = x; | 623 | min = x; |
639 | } | 624 | } |
640 | aeth |= x << IPS_AETH_CREDIT_SHIFT; | 625 | aeth |= x << IPATH_AETH_CREDIT_SHIFT; |
641 | } | 626 | } |
642 | return cpu_to_be32(aeth); | 627 | return cpu_to_be32(aeth); |
643 | } | 628 | } |
@@ -663,12 +648,22 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
663 | size_t sz; | 648 | size_t sz; |
664 | struct ib_qp *ret; | 649 | struct ib_qp *ret; |
665 | 650 | ||
666 | if (init_attr->cap.max_send_sge > 255 || | 651 | if (init_attr->cap.max_send_sge > ib_ipath_max_sges || |
667 | init_attr->cap.max_recv_sge > 255) { | 652 | init_attr->cap.max_recv_sge > ib_ipath_max_sges || |
653 | init_attr->cap.max_send_wr > ib_ipath_max_qp_wrs || | ||
654 | init_attr->cap.max_recv_wr > ib_ipath_max_qp_wrs) { | ||
668 | ret = ERR_PTR(-ENOMEM); | 655 | ret = ERR_PTR(-ENOMEM); |
669 | goto bail; | 656 | goto bail; |
670 | } | 657 | } |
671 | 658 | ||
659 | if (init_attr->cap.max_send_sge + | ||
660 | init_attr->cap.max_recv_sge + | ||
661 | init_attr->cap.max_send_wr + | ||
662 | init_attr->cap.max_recv_wr == 0) { | ||
663 | ret = ERR_PTR(-EINVAL); | ||
664 | goto bail; | ||
665 | } | ||
666 | |||
672 | switch (init_attr->qp_type) { | 667 | switch (init_attr->qp_type) { |
673 | case IB_QPT_UC: | 668 | case IB_QPT_UC: |
674 | case IB_QPT_RC: | 669 | case IB_QPT_RC: |
@@ -686,18 +681,26 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
686 | case IB_QPT_GSI: | 681 | case IB_QPT_GSI: |
687 | qp = kmalloc(sizeof(*qp), GFP_KERNEL); | 682 | qp = kmalloc(sizeof(*qp), GFP_KERNEL); |
688 | if (!qp) { | 683 | if (!qp) { |
684 | vfree(swq); | ||
689 | ret = ERR_PTR(-ENOMEM); | 685 | ret = ERR_PTR(-ENOMEM); |
690 | goto bail; | 686 | goto bail; |
691 | } | 687 | } |
692 | qp->r_rq.size = init_attr->cap.max_recv_wr + 1; | 688 | if (init_attr->srq) { |
693 | sz = sizeof(struct ipath_sge) * | 689 | qp->r_rq.size = 0; |
694 | init_attr->cap.max_recv_sge + | 690 | qp->r_rq.max_sge = 0; |
695 | sizeof(struct ipath_rwqe); | 691 | qp->r_rq.wq = NULL; |
696 | qp->r_rq.wq = vmalloc(qp->r_rq.size * sz); | 692 | } else { |
697 | if (!qp->r_rq.wq) { | 693 | qp->r_rq.size = init_attr->cap.max_recv_wr + 1; |
698 | kfree(qp); | 694 | qp->r_rq.max_sge = init_attr->cap.max_recv_sge; |
699 | ret = ERR_PTR(-ENOMEM); | 695 | sz = (sizeof(struct ipath_sge) * qp->r_rq.max_sge) + |
700 | goto bail; | 696 | sizeof(struct ipath_rwqe); |
697 | qp->r_rq.wq = vmalloc(qp->r_rq.size * sz); | ||
698 | if (!qp->r_rq.wq) { | ||
699 | kfree(qp); | ||
700 | vfree(swq); | ||
701 | ret = ERR_PTR(-ENOMEM); | ||
702 | goto bail; | ||
703 | } | ||
701 | } | 704 | } |
702 | 705 | ||
703 | /* | 706 | /* |
@@ -708,9 +711,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
708 | spin_lock_init(&qp->r_rq.lock); | 711 | spin_lock_init(&qp->r_rq.lock); |
709 | atomic_set(&qp->refcount, 0); | 712 | atomic_set(&qp->refcount, 0); |
710 | init_waitqueue_head(&qp->wait); | 713 | init_waitqueue_head(&qp->wait); |
711 | tasklet_init(&qp->s_task, | 714 | tasklet_init(&qp->s_task, ipath_do_ruc_send, |
712 | init_attr->qp_type == IB_QPT_RC ? | ||
713 | ipath_do_rc_send : ipath_do_uc_send, | ||
714 | (unsigned long)qp); | 715 | (unsigned long)qp); |
715 | INIT_LIST_HEAD(&qp->piowait); | 716 | INIT_LIST_HEAD(&qp->piowait); |
716 | INIT_LIST_HEAD(&qp->timerwait); | 717 | INIT_LIST_HEAD(&qp->timerwait); |
@@ -718,7 +719,6 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
718 | qp->s_wq = swq; | 719 | qp->s_wq = swq; |
719 | qp->s_size = init_attr->cap.max_send_wr + 1; | 720 | qp->s_size = init_attr->cap.max_send_wr + 1; |
720 | qp->s_max_sge = init_attr->cap.max_send_sge; | 721 | qp->s_max_sge = init_attr->cap.max_send_sge; |
721 | qp->r_rq.max_sge = init_attr->cap.max_recv_sge; | ||
722 | qp->s_flags = init_attr->sq_sig_type == IB_SIGNAL_REQ_WR ? | 722 | qp->s_flags = init_attr->sq_sig_type == IB_SIGNAL_REQ_WR ? |
723 | 1 << IPATH_S_SIGNAL_REQ_WR : 0; | 723 | 1 << IPATH_S_SIGNAL_REQ_WR : 0; |
724 | dev = to_idev(ibpd->device); | 724 | dev = to_idev(ibpd->device); |
@@ -888,18 +888,18 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc) | |||
888 | */ | 888 | */ |
889 | void ipath_get_credit(struct ipath_qp *qp, u32 aeth) | 889 | void ipath_get_credit(struct ipath_qp *qp, u32 aeth) |
890 | { | 890 | { |
891 | u32 credit = (aeth >> IPS_AETH_CREDIT_SHIFT) & IPS_AETH_CREDIT_MASK; | 891 | u32 credit = (aeth >> IPATH_AETH_CREDIT_SHIFT) & IPATH_AETH_CREDIT_MASK; |
892 | 892 | ||
893 | /* | 893 | /* |
894 | * If the credit is invalid, we can send | 894 | * If the credit is invalid, we can send |
895 | * as many packets as we like. Otherwise, we have to | 895 | * as many packets as we like. Otherwise, we have to |
896 | * honor the credit field. | 896 | * honor the credit field. |
897 | */ | 897 | */ |
898 | if (credit == IPS_AETH_CREDIT_INVAL) { | 898 | if (credit == IPATH_AETH_CREDIT_INVAL) |
899 | qp->s_lsn = (u32) -1; | 899 | qp->s_lsn = (u32) -1; |
900 | } else if (qp->s_lsn != (u32) -1) { | 900 | else if (qp->s_lsn != (u32) -1) { |
901 | /* Compute new LSN (i.e., MSN + credit) */ | 901 | /* Compute new LSN (i.e., MSN + credit) */ |
902 | credit = (aeth + credit_table[credit]) & IPS_MSN_MASK; | 902 | credit = (aeth + credit_table[credit]) & IPATH_MSN_MASK; |
903 | if (ipath_cmp24(credit, qp->s_lsn) > 0) | 903 | if (ipath_cmp24(credit, qp->s_lsn) > 0) |
904 | qp->s_lsn = credit; | 904 | qp->s_lsn = credit; |
905 | } | 905 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 493b1821a934..774d1615ce2f 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -31,7 +32,7 @@ | |||
31 | */ | 32 | */ |
32 | 33 | ||
33 | #include "ipath_verbs.h" | 34 | #include "ipath_verbs.h" |
34 | #include "ips_common.h" | 35 | #include "ipath_common.h" |
35 | 36 | ||
36 | /* cut down ridiculously long IB macro names */ | 37 | /* cut down ridiculously long IB macro names */ |
37 | #define OP(x) IB_OPCODE_RC_##x | 38 | #define OP(x) IB_OPCODE_RC_##x |
@@ -41,14 +42,14 @@ | |||
41 | * @qp: the QP who's SGE we're restarting | 42 | * @qp: the QP who's SGE we're restarting |
42 | * @wqe: the work queue to initialize the QP's SGE from | 43 | * @wqe: the work queue to initialize the QP's SGE from |
43 | * | 44 | * |
44 | * The QP s_lock should be held. | 45 | * The QP s_lock should be held and interrupts disabled. |
45 | */ | 46 | */ |
46 | static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe) | 47 | static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe) |
47 | { | 48 | { |
48 | struct ipath_ibdev *dev; | 49 | struct ipath_ibdev *dev; |
49 | u32 len; | 50 | u32 len; |
50 | 51 | ||
51 | len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) * | 52 | len = ((qp->s_psn - wqe->psn) & IPATH_PSN_MASK) * |
52 | ib_mtu_enum_to_int(qp->path_mtu); | 53 | ib_mtu_enum_to_int(qp->path_mtu); |
53 | qp->s_sge.sge = wqe->sg_list[0]; | 54 | qp->s_sge.sge = wqe->sg_list[0]; |
54 | qp->s_sge.sg_list = wqe->sg_list + 1; | 55 | qp->s_sge.sg_list = wqe->sg_list + 1; |
@@ -72,11 +73,10 @@ static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe) | |||
72 | * Return bth0 if constructed; otherwise, return 0. | 73 | * Return bth0 if constructed; otherwise, return 0. |
73 | * Note the QP s_lock must be held. | 74 | * Note the QP s_lock must be held. |
74 | */ | 75 | */ |
75 | static inline u32 ipath_make_rc_ack(struct ipath_qp *qp, | 76 | u32 ipath_make_rc_ack(struct ipath_qp *qp, |
76 | struct ipath_other_headers *ohdr, | 77 | struct ipath_other_headers *ohdr, |
77 | u32 pmtu) | 78 | u32 pmtu) |
78 | { | 79 | { |
79 | struct ipath_sge_state *ss; | ||
80 | u32 hwords; | 80 | u32 hwords; |
81 | u32 len; | 81 | u32 len; |
82 | u32 bth0; | 82 | u32 bth0; |
@@ -90,13 +90,12 @@ static inline u32 ipath_make_rc_ack(struct ipath_qp *qp, | |||
90 | */ | 90 | */ |
91 | switch (qp->s_ack_state) { | 91 | switch (qp->s_ack_state) { |
92 | case OP(RDMA_READ_REQUEST): | 92 | case OP(RDMA_READ_REQUEST): |
93 | ss = &qp->s_rdma_sge; | 93 | qp->s_cur_sge = &qp->s_rdma_sge; |
94 | len = qp->s_rdma_len; | 94 | len = qp->s_rdma_len; |
95 | if (len > pmtu) { | 95 | if (len > pmtu) { |
96 | len = pmtu; | 96 | len = pmtu; |
97 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST); | 97 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST); |
98 | } | 98 | } else |
99 | else | ||
100 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY); | 99 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY); |
101 | qp->s_rdma_len -= len; | 100 | qp->s_rdma_len -= len; |
102 | bth0 = qp->s_ack_state << 24; | 101 | bth0 = qp->s_ack_state << 24; |
@@ -108,7 +107,7 @@ static inline u32 ipath_make_rc_ack(struct ipath_qp *qp, | |||
108 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); | 107 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); |
109 | /* FALLTHROUGH */ | 108 | /* FALLTHROUGH */ |
110 | case OP(RDMA_READ_RESPONSE_MIDDLE): | 109 | case OP(RDMA_READ_RESPONSE_MIDDLE): |
111 | ss = &qp->s_rdma_sge; | 110 | qp->s_cur_sge = &qp->s_rdma_sge; |
112 | len = qp->s_rdma_len; | 111 | len = qp->s_rdma_len; |
113 | if (len > pmtu) | 112 | if (len > pmtu) |
114 | len = pmtu; | 113 | len = pmtu; |
@@ -127,41 +126,50 @@ static inline u32 ipath_make_rc_ack(struct ipath_qp *qp, | |||
127 | * We have to prevent new requests from changing | 126 | * We have to prevent new requests from changing |
128 | * the r_sge state while a ipath_verbs_send() | 127 | * the r_sge state while a ipath_verbs_send() |
129 | * is in progress. | 128 | * is in progress. |
130 | * Changing r_state allows the receiver | ||
131 | * to continue processing new packets. | ||
132 | * We do it here now instead of above so | ||
133 | * that we are sure the packet was sent before | ||
134 | * changing the state. | ||
135 | */ | 129 | */ |
136 | qp->r_state = OP(RDMA_READ_RESPONSE_LAST); | ||
137 | qp->s_ack_state = OP(ACKNOWLEDGE); | 130 | qp->s_ack_state = OP(ACKNOWLEDGE); |
138 | return 0; | 131 | bth0 = 0; |
132 | goto bail; | ||
139 | 133 | ||
140 | case OP(COMPARE_SWAP): | 134 | case OP(COMPARE_SWAP): |
141 | case OP(FETCH_ADD): | 135 | case OP(FETCH_ADD): |
142 | ss = NULL; | 136 | qp->s_cur_sge = NULL; |
143 | len = 0; | 137 | len = 0; |
144 | qp->r_state = OP(SEND_LAST); | 138 | /* |
145 | qp->s_ack_state = OP(ACKNOWLEDGE); | 139 | * Set the s_ack_state so the receive interrupt handler |
146 | bth0 = IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24; | 140 | * won't try to send an ACK (out of order) until this one |
141 | * is actually sent. | ||
142 | */ | ||
143 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST); | ||
144 | bth0 = OP(ATOMIC_ACKNOWLEDGE) << 24; | ||
147 | ohdr->u.at.aeth = ipath_compute_aeth(qp); | 145 | ohdr->u.at.aeth = ipath_compute_aeth(qp); |
148 | ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic); | 146 | ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->r_atomic_data); |
149 | hwords += sizeof(ohdr->u.at) / 4; | 147 | hwords += sizeof(ohdr->u.at) / 4; |
150 | break; | 148 | break; |
151 | 149 | ||
152 | default: | 150 | default: |
153 | /* Send a regular ACK. */ | 151 | /* Send a regular ACK. */ |
154 | ss = NULL; | 152 | qp->s_cur_sge = NULL; |
155 | len = 0; | 153 | len = 0; |
156 | qp->s_ack_state = OP(ACKNOWLEDGE); | 154 | /* |
157 | bth0 = qp->s_ack_state << 24; | 155 | * Set the s_ack_state so the receive interrupt handler |
158 | ohdr->u.aeth = ipath_compute_aeth(qp); | 156 | * won't try to send an ACK (out of order) until this one |
157 | * is actually sent. | ||
158 | */ | ||
159 | qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST); | ||
160 | bth0 = OP(ACKNOWLEDGE) << 24; | ||
161 | if (qp->s_nak_state) | ||
162 | ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) | | ||
163 | (qp->s_nak_state << | ||
164 | IPATH_AETH_CREDIT_SHIFT)); | ||
165 | else | ||
166 | ohdr->u.aeth = ipath_compute_aeth(qp); | ||
159 | hwords++; | 167 | hwords++; |
160 | } | 168 | } |
161 | qp->s_hdrwords = hwords; | 169 | qp->s_hdrwords = hwords; |
162 | qp->s_cur_sge = ss; | ||
163 | qp->s_cur_size = len; | 170 | qp->s_cur_size = len; |
164 | 171 | ||
172 | bail: | ||
165 | return bth0; | 173 | return bth0; |
166 | } | 174 | } |
167 | 175 | ||
@@ -174,11 +182,11 @@ static inline u32 ipath_make_rc_ack(struct ipath_qp *qp, | |||
174 | * @bth2p: pointer to the BTH PSN word | 182 | * @bth2p: pointer to the BTH PSN word |
175 | * | 183 | * |
176 | * Return 1 if constructed; otherwise, return 0. | 184 | * Return 1 if constructed; otherwise, return 0. |
177 | * Note the QP s_lock must be held. | 185 | * Note the QP s_lock must be held and interrupts disabled. |
178 | */ | 186 | */ |
179 | static inline int ipath_make_rc_req(struct ipath_qp *qp, | 187 | int ipath_make_rc_req(struct ipath_qp *qp, |
180 | struct ipath_other_headers *ohdr, | 188 | struct ipath_other_headers *ohdr, |
181 | u32 pmtu, u32 *bth0p, u32 *bth2p) | 189 | u32 pmtu, u32 *bth0p, u32 *bth2p) |
182 | { | 190 | { |
183 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | 191 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); |
184 | struct ipath_sge_state *ss; | 192 | struct ipath_sge_state *ss; |
@@ -257,7 +265,7 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
257 | break; | 265 | break; |
258 | 266 | ||
259 | case IB_WR_RDMA_WRITE: | 267 | case IB_WR_RDMA_WRITE: |
260 | if (newreq) | 268 | if (newreq && qp->s_lsn != (u32) -1) |
261 | qp->s_lsn++; | 269 | qp->s_lsn++; |
262 | /* FALLTHROUGH */ | 270 | /* FALLTHROUGH */ |
263 | case IB_WR_RDMA_WRITE_WITH_IMM: | 271 | case IB_WR_RDMA_WRITE_WITH_IMM: |
@@ -283,8 +291,7 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
283 | else { | 291 | else { |
284 | qp->s_state = | 292 | qp->s_state = |
285 | OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); | 293 | OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE); |
286 | /* Immediate data comes | 294 | /* Immediate data comes after RETH */ |
287 | * after RETH */ | ||
288 | ohdr->u.rc.imm_data = wqe->wr.imm_data; | 295 | ohdr->u.rc.imm_data = wqe->wr.imm_data; |
289 | hwords += 1; | 296 | hwords += 1; |
290 | if (wqe->wr.send_flags & IB_SEND_SOLICITED) | 297 | if (wqe->wr.send_flags & IB_SEND_SOLICITED) |
@@ -304,7 +311,8 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
304 | qp->s_state = OP(RDMA_READ_REQUEST); | 311 | qp->s_state = OP(RDMA_READ_REQUEST); |
305 | hwords += sizeof(ohdr->u.rc.reth) / 4; | 312 | hwords += sizeof(ohdr->u.rc.reth) / 4; |
306 | if (newreq) { | 313 | if (newreq) { |
307 | qp->s_lsn++; | 314 | if (qp->s_lsn != (u32) -1) |
315 | qp->s_lsn++; | ||
308 | /* | 316 | /* |
309 | * Adjust s_next_psn to count the | 317 | * Adjust s_next_psn to count the |
310 | * expected number of responses. | 318 | * expected number of responses. |
@@ -335,7 +343,8 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
335 | wqe->wr.wr.atomic.compare_add); | 343 | wqe->wr.wr.atomic.compare_add); |
336 | hwords += sizeof(struct ib_atomic_eth) / 4; | 344 | hwords += sizeof(struct ib_atomic_eth) / 4; |
337 | if (newreq) { | 345 | if (newreq) { |
338 | qp->s_lsn++; | 346 | if (qp->s_lsn != (u32) -1) |
347 | qp->s_lsn++; | ||
339 | wqe->lpsn = wqe->psn; | 348 | wqe->lpsn = wqe->psn; |
340 | } | 349 | } |
341 | if (++qp->s_cur == qp->s_size) | 350 | if (++qp->s_cur == qp->s_size) |
@@ -352,9 +361,14 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
352 | if (qp->s_tail >= qp->s_size) | 361 | if (qp->s_tail >= qp->s_size) |
353 | qp->s_tail = 0; | 362 | qp->s_tail = 0; |
354 | } | 363 | } |
355 | bth2 |= qp->s_psn++ & IPS_PSN_MASK; | 364 | bth2 |= qp->s_psn++ & IPATH_PSN_MASK; |
356 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) | 365 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) |
357 | qp->s_next_psn = qp->s_psn; | 366 | qp->s_next_psn = qp->s_psn; |
367 | /* | ||
368 | * Put the QP on the pending list so lost ACKs will cause | ||
369 | * a retry. More than one request can be pending so the | ||
370 | * QP may already be on the dev->pending list. | ||
371 | */ | ||
358 | spin_lock(&dev->pending_lock); | 372 | spin_lock(&dev->pending_lock); |
359 | if (list_empty(&qp->timerwait)) | 373 | if (list_empty(&qp->timerwait)) |
360 | list_add_tail(&qp->timerwait, | 374 | list_add_tail(&qp->timerwait, |
@@ -364,8 +378,8 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
364 | 378 | ||
365 | case OP(RDMA_READ_RESPONSE_FIRST): | 379 | case OP(RDMA_READ_RESPONSE_FIRST): |
366 | /* | 380 | /* |
367 | * This case can only happen if a send is restarted. See | 381 | * This case can only happen if a send is restarted. |
368 | * ipath_restart_rc(). | 382 | * See ipath_restart_rc(). |
369 | */ | 383 | */ |
370 | ipath_init_restart(qp, wqe); | 384 | ipath_init_restart(qp, wqe); |
371 | /* FALLTHROUGH */ | 385 | /* FALLTHROUGH */ |
@@ -373,7 +387,7 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
373 | qp->s_state = OP(SEND_MIDDLE); | 387 | qp->s_state = OP(SEND_MIDDLE); |
374 | /* FALLTHROUGH */ | 388 | /* FALLTHROUGH */ |
375 | case OP(SEND_MIDDLE): | 389 | case OP(SEND_MIDDLE): |
376 | bth2 = qp->s_psn++ & IPS_PSN_MASK; | 390 | bth2 = qp->s_psn++ & IPATH_PSN_MASK; |
377 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) | 391 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) |
378 | qp->s_next_psn = qp->s_psn; | 392 | qp->s_next_psn = qp->s_psn; |
379 | ss = &qp->s_sge; | 393 | ss = &qp->s_sge; |
@@ -415,7 +429,7 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
415 | qp->s_state = OP(RDMA_WRITE_MIDDLE); | 429 | qp->s_state = OP(RDMA_WRITE_MIDDLE); |
416 | /* FALLTHROUGH */ | 430 | /* FALLTHROUGH */ |
417 | case OP(RDMA_WRITE_MIDDLE): | 431 | case OP(RDMA_WRITE_MIDDLE): |
418 | bth2 = qp->s_psn++ & IPS_PSN_MASK; | 432 | bth2 = qp->s_psn++ & IPATH_PSN_MASK; |
419 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) | 433 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) |
420 | qp->s_next_psn = qp->s_psn; | 434 | qp->s_next_psn = qp->s_psn; |
421 | ss = &qp->s_sge; | 435 | ss = &qp->s_sge; |
@@ -452,7 +466,7 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
452 | * See ipath_restart_rc(). | 466 | * See ipath_restart_rc(). |
453 | */ | 467 | */ |
454 | ipath_init_restart(qp, wqe); | 468 | ipath_init_restart(qp, wqe); |
455 | len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) * pmtu; | 469 | len = ((qp->s_psn - wqe->psn) & IPATH_PSN_MASK) * pmtu; |
456 | ohdr->u.rc.reth.vaddr = | 470 | ohdr->u.rc.reth.vaddr = |
457 | cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len); | 471 | cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len); |
458 | ohdr->u.rc.reth.rkey = | 472 | ohdr->u.rc.reth.rkey = |
@@ -460,7 +474,7 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, | |||
460 | ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len); | 474 | ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len); |
461 | qp->s_state = OP(RDMA_READ_REQUEST); | 475 | qp->s_state = OP(RDMA_READ_REQUEST); |
462 | hwords += sizeof(ohdr->u.rc.reth) / 4; | 476 | hwords += sizeof(ohdr->u.rc.reth) / 4; |
463 | bth2 = qp->s_psn++ & IPS_PSN_MASK; | 477 | bth2 = qp->s_psn++ & IPATH_PSN_MASK; |
464 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) | 478 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) |
465 | qp->s_next_psn = qp->s_psn; | 479 | qp->s_next_psn = qp->s_psn; |
466 | ss = NULL; | 480 | ss = NULL; |
@@ -496,189 +510,169 @@ done: | |||
496 | return 0; | 510 | return 0; |
497 | } | 511 | } |
498 | 512 | ||
499 | static inline void ipath_make_rc_grh(struct ipath_qp *qp, | ||
500 | struct ib_global_route *grh, | ||
501 | u32 nwords) | ||
502 | { | ||
503 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | ||
504 | |||
505 | /* GRH header size in 32-bit words. */ | ||
506 | qp->s_hdrwords += 10; | ||
507 | qp->s_hdr.u.l.grh.version_tclass_flow = | ||
508 | cpu_to_be32((6 << 28) | | ||
509 | (grh->traffic_class << 20) | | ||
510 | grh->flow_label); | ||
511 | qp->s_hdr.u.l.grh.paylen = | ||
512 | cpu_to_be16(((qp->s_hdrwords - 12) + nwords + | ||
513 | SIZE_OF_CRC) << 2); | ||
514 | /* next_hdr is defined by C8-7 in ch. 8.4.1 */ | ||
515 | qp->s_hdr.u.l.grh.next_hdr = 0x1B; | ||
516 | qp->s_hdr.u.l.grh.hop_limit = grh->hop_limit; | ||
517 | /* The SGID is 32-bit aligned. */ | ||
518 | qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = dev->gid_prefix; | ||
519 | qp->s_hdr.u.l.grh.sgid.global.interface_id = | ||
520 | ipath_layer_get_guid(dev->dd); | ||
521 | qp->s_hdr.u.l.grh.dgid = grh->dgid; | ||
522 | } | ||
523 | |||
524 | /** | 513 | /** |
525 | * ipath_do_rc_send - perform a send on an RC QP | 514 | * send_rc_ack - Construct an ACK packet and send it |
526 | * @data: contains a pointer to the QP | 515 | * @qp: a pointer to the QP |
527 | * | 516 | * |
528 | * Process entries in the send work queue until credit or queue is | 517 | * This is called from ipath_rc_rcv() and only uses the receive |
529 | * exhausted. Only allow one CPU to send a packet per QP (tasklet). | 518 | * side QP state. |
530 | * Otherwise, after we drop the QP s_lock, two threads could send | 519 | * Note that RDMA reads are handled in the send side QP state and tasklet. |
531 | * packets out of order. | ||
532 | */ | 520 | */ |
533 | void ipath_do_rc_send(unsigned long data) | 521 | static void send_rc_ack(struct ipath_qp *qp) |
534 | { | 522 | { |
535 | struct ipath_qp *qp = (struct ipath_qp *)data; | ||
536 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | 523 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); |
537 | unsigned long flags; | ||
538 | u16 lrh0; | 524 | u16 lrh0; |
539 | u32 nwords; | ||
540 | u32 extra_bytes; | ||
541 | u32 bth0; | 525 | u32 bth0; |
542 | u32 bth2; | 526 | u32 hwords; |
543 | u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); | 527 | struct ipath_ib_header hdr; |
544 | struct ipath_other_headers *ohdr; | 528 | struct ipath_other_headers *ohdr; |
545 | 529 | ||
546 | if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags)) | ||
547 | goto bail; | ||
548 | |||
549 | if (unlikely(qp->remote_ah_attr.dlid == | ||
550 | ipath_layer_get_lid(dev->dd))) { | ||
551 | struct ib_wc wc; | ||
552 | |||
553 | /* | ||
554 | * Pass in an uninitialized ib_wc to be consistent with | ||
555 | * other places where ipath_ruc_loopback() is called. | ||
556 | */ | ||
557 | ipath_ruc_loopback(qp, &wc); | ||
558 | goto clear; | ||
559 | } | ||
560 | |||
561 | ohdr = &qp->s_hdr.u.oth; | ||
562 | if (qp->remote_ah_attr.ah_flags & IB_AH_GRH) | ||
563 | ohdr = &qp->s_hdr.u.l.oth; | ||
564 | |||
565 | again: | ||
566 | /* Check for a constructed packet to be sent. */ | ||
567 | if (qp->s_hdrwords != 0) { | ||
568 | /* | ||
569 | * If no PIO bufs are available, return. An interrupt will | ||
570 | * call ipath_ib_piobufavail() when one is available. | ||
571 | */ | ||
572 | _VERBS_INFO("h %u %p\n", qp->s_hdrwords, &qp->s_hdr); | ||
573 | _VERBS_INFO("d %u %p %u %p %u %u %u %u\n", qp->s_cur_size, | ||
574 | qp->s_cur_sge->sg_list, | ||
575 | qp->s_cur_sge->num_sge, | ||
576 | qp->s_cur_sge->sge.vaddr, | ||
577 | qp->s_cur_sge->sge.sge_length, | ||
578 | qp->s_cur_sge->sge.length, | ||
579 | qp->s_cur_sge->sge.m, | ||
580 | qp->s_cur_sge->sge.n); | ||
581 | if (ipath_verbs_send(dev->dd, qp->s_hdrwords, | ||
582 | (u32 *) &qp->s_hdr, qp->s_cur_size, | ||
583 | qp->s_cur_sge)) { | ||
584 | ipath_no_bufs_available(qp, dev); | ||
585 | goto bail; | ||
586 | } | ||
587 | dev->n_unicast_xmit++; | ||
588 | /* Record that we sent the packet and s_hdr is empty. */ | ||
589 | qp->s_hdrwords = 0; | ||
590 | } | ||
591 | |||
592 | /* | ||
593 | * The lock is needed to synchronize between setting | ||
594 | * qp->s_ack_state, resend timer, and post_send(). | ||
595 | */ | ||
596 | spin_lock_irqsave(&qp->s_lock, flags); | ||
597 | |||
598 | /* Sending responses has higher priority over sending requests. */ | ||
599 | if (qp->s_ack_state != OP(ACKNOWLEDGE) && | ||
600 | (bth0 = ipath_make_rc_ack(qp, ohdr, pmtu)) != 0) | ||
601 | bth2 = qp->s_ack_psn++ & IPS_PSN_MASK; | ||
602 | else if (!ipath_make_rc_req(qp, ohdr, pmtu, &bth0, &bth2)) | ||
603 | goto done; | ||
604 | |||
605 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
606 | |||
607 | /* Construct the header. */ | 530 | /* Construct the header. */ |
608 | extra_bytes = (4 - qp->s_cur_size) & 3; | 531 | ohdr = &hdr.u.oth; |
609 | nwords = (qp->s_cur_size + extra_bytes) >> 2; | 532 | lrh0 = IPATH_LRH_BTH; |
610 | lrh0 = IPS_LRH_BTH; | 533 | /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */ |
534 | hwords = 6; | ||
611 | if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) { | 535 | if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) { |
612 | ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, nwords); | 536 | hwords += ipath_make_grh(dev, &hdr.u.l.grh, |
613 | lrh0 = IPS_LRH_GRH; | 537 | &qp->remote_ah_attr.grh, |
538 | hwords, 0); | ||
539 | ohdr = &hdr.u.l.oth; | ||
540 | lrh0 = IPATH_LRH_GRH; | ||
614 | } | 541 | } |
542 | /* read pkey_index w/o lock (its atomic) */ | ||
543 | bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); | ||
544 | if (qp->r_nak_state) | ||
545 | ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) | | ||
546 | (qp->r_nak_state << | ||
547 | IPATH_AETH_CREDIT_SHIFT)); | ||
548 | else | ||
549 | ohdr->u.aeth = ipath_compute_aeth(qp); | ||
550 | if (qp->r_ack_state >= OP(COMPARE_SWAP)) { | ||
551 | bth0 |= OP(ATOMIC_ACKNOWLEDGE) << 24; | ||
552 | ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->r_atomic_data); | ||
553 | hwords += sizeof(ohdr->u.at.atomic_ack_eth) / 4; | ||
554 | } else | ||
555 | bth0 |= OP(ACKNOWLEDGE) << 24; | ||
615 | lrh0 |= qp->remote_ah_attr.sl << 4; | 556 | lrh0 |= qp->remote_ah_attr.sl << 4; |
616 | qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); | 557 | hdr.lrh[0] = cpu_to_be16(lrh0); |
617 | qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); | 558 | hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); |
618 | qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + | 559 | hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC); |
619 | SIZE_OF_CRC); | 560 | hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); |
620 | qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); | ||
621 | bth0 |= ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); | ||
622 | bth0 |= extra_bytes << 20; | ||
623 | ohdr->bth[0] = cpu_to_be32(bth0); | 561 | ohdr->bth[0] = cpu_to_be32(bth0); |
624 | ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); | 562 | ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); |
625 | ohdr->bth[2] = cpu_to_be32(bth2); | 563 | ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK); |
626 | 564 | ||
627 | /* Check for more work to do. */ | 565 | /* |
628 | goto again; | 566 | * If we can send the ACK, clear the ACK state. |
567 | */ | ||
568 | if (ipath_verbs_send(dev->dd, hwords, (u32 *) &hdr, 0, NULL) == 0) { | ||
569 | qp->r_ack_state = OP(ACKNOWLEDGE); | ||
570 | dev->n_unicast_xmit++; | ||
571 | } else { | ||
572 | /* | ||
573 | * We are out of PIO buffers at the moment. | ||
574 | * Pass responsibility for sending the ACK to the | ||
575 | * send tasklet so that when a PIO buffer becomes | ||
576 | * available, the ACK is sent ahead of other outgoing | ||
577 | * packets. | ||
578 | */ | ||
579 | dev->n_rc_qacks++; | ||
580 | spin_lock_irq(&qp->s_lock); | ||
581 | /* Don't coalesce if a RDMA read or atomic is pending. */ | ||
582 | if (qp->s_ack_state == OP(ACKNOWLEDGE) || | ||
583 | qp->s_ack_state < OP(RDMA_READ_REQUEST)) { | ||
584 | qp->s_ack_state = qp->r_ack_state; | ||
585 | qp->s_nak_state = qp->r_nak_state; | ||
586 | qp->s_ack_psn = qp->r_ack_psn; | ||
587 | qp->r_ack_state = OP(ACKNOWLEDGE); | ||
588 | } | ||
589 | spin_unlock_irq(&qp->s_lock); | ||
629 | 590 | ||
630 | done: | 591 | /* Call ipath_do_rc_send() in another thread. */ |
631 | spin_unlock_irqrestore(&qp->s_lock, flags); | 592 | tasklet_hi_schedule(&qp->s_task); |
632 | clear: | 593 | } |
633 | clear_bit(IPATH_S_BUSY, &qp->s_flags); | ||
634 | bail: | ||
635 | return; | ||
636 | } | 594 | } |
637 | 595 | ||
638 | static void send_rc_ack(struct ipath_qp *qp) | 596 | /** |
597 | * reset_psn - reset the QP state to send starting from PSN | ||
598 | * @qp: the QP | ||
599 | * @psn: the packet sequence number to restart at | ||
600 | * | ||
601 | * This is called from ipath_rc_rcv() to process an incoming RC ACK | ||
602 | * for the given QP. | ||
603 | * Called at interrupt level with the QP s_lock held. | ||
604 | */ | ||
605 | static void reset_psn(struct ipath_qp *qp, u32 psn) | ||
639 | { | 606 | { |
640 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | 607 | u32 n = qp->s_last; |
641 | u16 lrh0; | 608 | struct ipath_swqe *wqe = get_swqe_ptr(qp, n); |
642 | u32 bth0; | 609 | u32 opcode; |
643 | struct ipath_other_headers *ohdr; | ||
644 | 610 | ||
645 | /* Construct the header. */ | 611 | qp->s_cur = n; |
646 | ohdr = &qp->s_hdr.u.oth; | 612 | |
647 | lrh0 = IPS_LRH_BTH; | 613 | /* |
648 | /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */ | 614 | * If we are starting the request from the beginning, |
649 | qp->s_hdrwords = 6; | 615 | * let the normal send code handle initialization. |
650 | if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) { | 616 | */ |
651 | ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, 0); | 617 | if (ipath_cmp24(psn, wqe->psn) <= 0) { |
652 | ohdr = &qp->s_hdr.u.l.oth; | 618 | qp->s_state = OP(SEND_LAST); |
653 | lrh0 = IPS_LRH_GRH; | 619 | goto done; |
654 | } | 620 | } |
655 | bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); | 621 | |
656 | ohdr->u.aeth = ipath_compute_aeth(qp); | 622 | /* Find the work request opcode corresponding to the given PSN. */ |
657 | if (qp->s_ack_state >= OP(COMPARE_SWAP)) { | 623 | opcode = wqe->wr.opcode; |
658 | bth0 |= IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24; | 624 | for (;;) { |
659 | ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic); | 625 | int diff; |
660 | qp->s_hdrwords += sizeof(ohdr->u.at.atomic_ack_eth) / 4; | 626 | |
627 | if (++n == qp->s_size) | ||
628 | n = 0; | ||
629 | if (n == qp->s_tail) | ||
630 | break; | ||
631 | wqe = get_swqe_ptr(qp, n); | ||
632 | diff = ipath_cmp24(psn, wqe->psn); | ||
633 | if (diff < 0) | ||
634 | break; | ||
635 | qp->s_cur = n; | ||
636 | /* | ||
637 | * If we are starting the request from the beginning, | ||
638 | * let the normal send code handle initialization. | ||
639 | */ | ||
640 | if (diff == 0) { | ||
641 | qp->s_state = OP(SEND_LAST); | ||
642 | goto done; | ||
643 | } | ||
644 | opcode = wqe->wr.opcode; | ||
661 | } | 645 | } |
662 | else | ||
663 | bth0 |= OP(ACKNOWLEDGE) << 24; | ||
664 | lrh0 |= qp->remote_ah_attr.sl << 4; | ||
665 | qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); | ||
666 | qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); | ||
667 | qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + SIZE_OF_CRC); | ||
668 | qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); | ||
669 | ohdr->bth[0] = cpu_to_be32(bth0); | ||
670 | ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); | ||
671 | ohdr->bth[2] = cpu_to_be32(qp->s_ack_psn & IPS_PSN_MASK); | ||
672 | 646 | ||
673 | /* | 647 | /* |
674 | * If we can send the ACK, clear the ACK state. | 648 | * Set the state to restart in the middle of a request. |
649 | * Don't change the s_sge, s_cur_sge, or s_cur_size. | ||
650 | * See ipath_do_rc_send(). | ||
675 | */ | 651 | */ |
676 | if (ipath_verbs_send(dev->dd, qp->s_hdrwords, (u32 *) &qp->s_hdr, | 652 | switch (opcode) { |
677 | 0, NULL) == 0) { | 653 | case IB_WR_SEND: |
678 | qp->s_ack_state = OP(ACKNOWLEDGE); | 654 | case IB_WR_SEND_WITH_IMM: |
679 | dev->n_rc_qacks++; | 655 | qp->s_state = OP(RDMA_READ_RESPONSE_FIRST); |
680 | dev->n_unicast_xmit++; | 656 | break; |
657 | |||
658 | case IB_WR_RDMA_WRITE: | ||
659 | case IB_WR_RDMA_WRITE_WITH_IMM: | ||
660 | qp->s_state = OP(RDMA_READ_RESPONSE_LAST); | ||
661 | break; | ||
662 | |||
663 | case IB_WR_RDMA_READ: | ||
664 | qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE); | ||
665 | break; | ||
666 | |||
667 | default: | ||
668 | /* | ||
669 | * This case shouldn't happen since its only | ||
670 | * one PSN per req. | ||
671 | */ | ||
672 | qp->s_state = OP(SEND_LAST); | ||
681 | } | 673 | } |
674 | done: | ||
675 | qp->s_psn = psn; | ||
682 | } | 676 | } |
683 | 677 | ||
684 | /** | 678 | /** |
@@ -687,13 +681,12 @@ static void send_rc_ack(struct ipath_qp *qp) | |||
687 | * @psn: packet sequence number for the request | 681 | * @psn: packet sequence number for the request |
688 | * @wc: the work completion request | 682 | * @wc: the work completion request |
689 | * | 683 | * |
690 | * The QP s_lock should be held. | 684 | * The QP s_lock should be held and interrupts disabled. |
691 | */ | 685 | */ |
692 | void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) | 686 | void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) |
693 | { | 687 | { |
694 | struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); | 688 | struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); |
695 | struct ipath_ibdev *dev; | 689 | struct ipath_ibdev *dev; |
696 | u32 n; | ||
697 | 690 | ||
698 | /* | 691 | /* |
699 | * If there are no requests pending, we are done. | 692 | * If there are no requests pending, we are done. |
@@ -735,62 +728,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) | |||
735 | else | 728 | else |
736 | dev->n_rc_resends += (int)qp->s_psn - (int)psn; | 729 | dev->n_rc_resends += (int)qp->s_psn - (int)psn; |
737 | 730 | ||
738 | /* | 731 | reset_psn(qp, psn); |
739 | * If we are starting the request from the beginning, let the normal | ||
740 | * send code handle initialization. | ||
741 | */ | ||
742 | qp->s_cur = qp->s_last; | ||
743 | if (ipath_cmp24(psn, wqe->psn) <= 0) { | ||
744 | qp->s_state = OP(SEND_LAST); | ||
745 | qp->s_psn = wqe->psn; | ||
746 | } else { | ||
747 | n = qp->s_cur; | ||
748 | for (;;) { | ||
749 | if (++n == qp->s_size) | ||
750 | n = 0; | ||
751 | if (n == qp->s_tail) { | ||
752 | if (ipath_cmp24(psn, qp->s_next_psn) >= 0) { | ||
753 | qp->s_cur = n; | ||
754 | wqe = get_swqe_ptr(qp, n); | ||
755 | } | ||
756 | break; | ||
757 | } | ||
758 | wqe = get_swqe_ptr(qp, n); | ||
759 | if (ipath_cmp24(psn, wqe->psn) < 0) | ||
760 | break; | ||
761 | qp->s_cur = n; | ||
762 | } | ||
763 | qp->s_psn = psn; | ||
764 | |||
765 | /* | ||
766 | * Reset the state to restart in the middle of a request. | ||
767 | * Don't change the s_sge, s_cur_sge, or s_cur_size. | ||
768 | * See ipath_do_rc_send(). | ||
769 | */ | ||
770 | switch (wqe->wr.opcode) { | ||
771 | case IB_WR_SEND: | ||
772 | case IB_WR_SEND_WITH_IMM: | ||
773 | qp->s_state = OP(RDMA_READ_RESPONSE_FIRST); | ||
774 | break; | ||
775 | |||
776 | case IB_WR_RDMA_WRITE: | ||
777 | case IB_WR_RDMA_WRITE_WITH_IMM: | ||
778 | qp->s_state = OP(RDMA_READ_RESPONSE_LAST); | ||
779 | break; | ||
780 | |||
781 | case IB_WR_RDMA_READ: | ||
782 | qp->s_state = | ||
783 | OP(RDMA_READ_RESPONSE_MIDDLE); | ||
784 | break; | ||
785 | |||
786 | default: | ||
787 | /* | ||
788 | * This case shouldn't happen since its only | ||
789 | * one PSN per req. | ||
790 | */ | ||
791 | qp->s_state = OP(SEND_LAST); | ||
792 | } | ||
793 | } | ||
794 | 732 | ||
795 | done: | 733 | done: |
796 | tasklet_hi_schedule(&qp->s_task); | 734 | tasklet_hi_schedule(&qp->s_task); |
@@ -800,76 +738,14 @@ bail: | |||
800 | } | 738 | } |
801 | 739 | ||
802 | /** | 740 | /** |
803 | * reset_psn - reset the QP state to send starting from PSN | ||
804 | * @qp: the QP | ||
805 | * @psn: the packet sequence number to restart at | ||
806 | * | ||
807 | * This is called from ipath_rc_rcv() to process an incoming RC ACK | ||
808 | * for the given QP. | ||
809 | * Called at interrupt level with the QP s_lock held. | ||
810 | */ | ||
811 | static void reset_psn(struct ipath_qp *qp, u32 psn) | ||
812 | { | ||
813 | struct ipath_swqe *wqe; | ||
814 | u32 n; | ||
815 | |||
816 | n = qp->s_cur; | ||
817 | wqe = get_swqe_ptr(qp, n); | ||
818 | for (;;) { | ||
819 | if (++n == qp->s_size) | ||
820 | n = 0; | ||
821 | if (n == qp->s_tail) { | ||
822 | if (ipath_cmp24(psn, qp->s_next_psn) >= 0) { | ||
823 | qp->s_cur = n; | ||
824 | wqe = get_swqe_ptr(qp, n); | ||
825 | } | ||
826 | break; | ||
827 | } | ||
828 | wqe = get_swqe_ptr(qp, n); | ||
829 | if (ipath_cmp24(psn, wqe->psn) < 0) | ||
830 | break; | ||
831 | qp->s_cur = n; | ||
832 | } | ||
833 | qp->s_psn = psn; | ||
834 | |||
835 | /* | ||
836 | * Set the state to restart in the middle of a | ||
837 | * request. Don't change the s_sge, s_cur_sge, or | ||
838 | * s_cur_size. See ipath_do_rc_send(). | ||
839 | */ | ||
840 | switch (wqe->wr.opcode) { | ||
841 | case IB_WR_SEND: | ||
842 | case IB_WR_SEND_WITH_IMM: | ||
843 | qp->s_state = OP(RDMA_READ_RESPONSE_FIRST); | ||
844 | break; | ||
845 | |||
846 | case IB_WR_RDMA_WRITE: | ||
847 | case IB_WR_RDMA_WRITE_WITH_IMM: | ||
848 | qp->s_state = OP(RDMA_READ_RESPONSE_LAST); | ||
849 | break; | ||
850 | |||
851 | case IB_WR_RDMA_READ: | ||
852 | qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE); | ||
853 | break; | ||
854 | |||
855 | default: | ||
856 | /* | ||
857 | * This case shouldn't happen since its only | ||
858 | * one PSN per req. | ||
859 | */ | ||
860 | qp->s_state = OP(SEND_LAST); | ||
861 | } | ||
862 | } | ||
863 | |||
864 | /** | ||
865 | * do_rc_ack - process an incoming RC ACK | 741 | * do_rc_ack - process an incoming RC ACK |
866 | * @qp: the QP the ACK came in on | 742 | * @qp: the QP the ACK came in on |
867 | * @psn: the packet sequence number of the ACK | 743 | * @psn: the packet sequence number of the ACK |
868 | * @opcode: the opcode of the request that resulted in the ACK | 744 | * @opcode: the opcode of the request that resulted in the ACK |
869 | * | 745 | * |
870 | * This is called from ipath_rc_rcv() to process an incoming RC ACK | 746 | * This is called from ipath_rc_rcv_resp() to process an incoming RC ACK |
871 | * for the given QP. | 747 | * for the given QP. |
872 | * Called at interrupt level with the QP s_lock held. | 748 | * Called at interrupt level with the QP s_lock held and interrupts disabled. |
873 | * Returns 1 if OK, 0 if current operation should be aborted (NAK). | 749 | * Returns 1 if OK, 0 if current operation should be aborted (NAK). |
874 | */ | 750 | */ |
875 | static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | 751 | static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) |
@@ -1006,26 +882,16 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
1006 | if (qp->s_last == qp->s_tail) | 882 | if (qp->s_last == qp->s_tail) |
1007 | goto bail; | 883 | goto bail; |
1008 | 884 | ||
1009 | /* The last valid PSN seen is the previous request's. */ | 885 | /* The last valid PSN is the previous PSN. */ |
1010 | qp->s_last_psn = wqe->psn - 1; | 886 | qp->s_last_psn = psn - 1; |
1011 | 887 | ||
1012 | dev->n_rc_resends += (int)qp->s_psn - (int)psn; | 888 | dev->n_rc_resends += (int)qp->s_psn - (int)psn; |
1013 | 889 | ||
1014 | /* | 890 | reset_psn(qp, psn); |
1015 | * If we are starting the request from the beginning, let | ||
1016 | * the normal send code handle initialization. | ||
1017 | */ | ||
1018 | qp->s_cur = qp->s_last; | ||
1019 | wqe = get_swqe_ptr(qp, qp->s_cur); | ||
1020 | if (ipath_cmp24(psn, wqe->psn) <= 0) { | ||
1021 | qp->s_state = OP(SEND_LAST); | ||
1022 | qp->s_psn = wqe->psn; | ||
1023 | } else | ||
1024 | reset_psn(qp, psn); | ||
1025 | 891 | ||
1026 | qp->s_rnr_timeout = | 892 | qp->s_rnr_timeout = |
1027 | ib_ipath_rnr_table[(aeth >> IPS_AETH_CREDIT_SHIFT) & | 893 | ib_ipath_rnr_table[(aeth >> IPATH_AETH_CREDIT_SHIFT) & |
1028 | IPS_AETH_CREDIT_MASK]; | 894 | IPATH_AETH_CREDIT_MASK]; |
1029 | ipath_insert_rnr_queue(qp); | 895 | ipath_insert_rnr_queue(qp); |
1030 | goto bail; | 896 | goto bail; |
1031 | 897 | ||
@@ -1033,8 +899,8 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
1033 | /* The last valid PSN seen is the previous request's. */ | 899 | /* The last valid PSN seen is the previous request's. */ |
1034 | if (qp->s_last != qp->s_tail) | 900 | if (qp->s_last != qp->s_tail) |
1035 | qp->s_last_psn = wqe->psn - 1; | 901 | qp->s_last_psn = wqe->psn - 1; |
1036 | switch ((aeth >> IPS_AETH_CREDIT_SHIFT) & | 902 | switch ((aeth >> IPATH_AETH_CREDIT_SHIFT) & |
1037 | IPS_AETH_CREDIT_MASK) { | 903 | IPATH_AETH_CREDIT_MASK) { |
1038 | case 0: /* PSN sequence error */ | 904 | case 0: /* PSN sequence error */ |
1039 | dev->n_seq_naks++; | 905 | dev->n_seq_naks++; |
1040 | /* | 906 | /* |
@@ -1182,32 +1048,33 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, | |||
1182 | goto ack_done; | 1048 | goto ack_done; |
1183 | } | 1049 | } |
1184 | rdma_read: | 1050 | rdma_read: |
1185 | if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST))) | 1051 | if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST))) |
1186 | goto ack_done; | 1052 | goto ack_done; |
1187 | if (unlikely(tlen != (hdrsize + pmtu + 4))) | 1053 | if (unlikely(tlen != (hdrsize + pmtu + 4))) |
1188 | goto ack_done; | 1054 | goto ack_done; |
1189 | if (unlikely(pmtu >= qp->s_len)) | 1055 | if (unlikely(pmtu >= qp->s_len)) |
1190 | goto ack_done; | 1056 | goto ack_done; |
1191 | /* We got a response so update the timeout. */ | 1057 | /* We got a response so update the timeout. */ |
1192 | if (unlikely(qp->s_last == qp->s_tail || | 1058 | if (unlikely(qp->s_last == qp->s_tail || |
1193 | get_swqe_ptr(qp, qp->s_last)->wr.opcode != | 1059 | get_swqe_ptr(qp, qp->s_last)->wr.opcode != |
1194 | IB_WR_RDMA_READ)) | 1060 | IB_WR_RDMA_READ)) |
1195 | goto ack_done; | 1061 | goto ack_done; |
1196 | spin_lock(&dev->pending_lock); | 1062 | spin_lock(&dev->pending_lock); |
1197 | if (qp->s_rnr_timeout == 0 && !list_empty(&qp->timerwait)) | 1063 | if (qp->s_rnr_timeout == 0 && !list_empty(&qp->timerwait)) |
1198 | list_move_tail(&qp->timerwait, | 1064 | list_move_tail(&qp->timerwait, |
1199 | &dev->pending[dev->pending_index]); | 1065 | &dev->pending[dev->pending_index]); |
1200 | spin_unlock(&dev->pending_lock); | 1066 | spin_unlock(&dev->pending_lock); |
1201 | /* | 1067 | /* |
1202 | * Update the RDMA receive state but do the copy w/o holding the | 1068 | * Update the RDMA receive state but do the copy w/o |
1203 | * locks and blocking interrupts. XXX Yet another place that | 1069 | * holding the locks and blocking interrupts. |
1204 | * affects relaxed RDMA order since we don't want s_sge modified. | 1070 | * XXX Yet another place that affects relaxed RDMA order |
1205 | */ | 1071 | * since we don't want s_sge modified. |
1206 | qp->s_len -= pmtu; | 1072 | */ |
1207 | qp->s_last_psn = psn; | 1073 | qp->s_len -= pmtu; |
1208 | spin_unlock_irqrestore(&qp->s_lock, flags); | 1074 | qp->s_last_psn = psn; |
1209 | ipath_copy_sge(&qp->s_sge, data, pmtu); | 1075 | spin_unlock_irqrestore(&qp->s_lock, flags); |
1210 | goto bail; | 1076 | ipath_copy_sge(&qp->s_sge, data, pmtu); |
1077 | goto bail; | ||
1211 | 1078 | ||
1212 | case OP(RDMA_READ_RESPONSE_LAST): | 1079 | case OP(RDMA_READ_RESPONSE_LAST): |
1213 | /* ACKs READ req. */ | 1080 | /* ACKs READ req. */ |
@@ -1230,18 +1097,12 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, | |||
1230 | * ICRC (4). | 1097 | * ICRC (4). |
1231 | */ | 1098 | */ |
1232 | if (unlikely(tlen <= (hdrsize + pad + 8))) { | 1099 | if (unlikely(tlen <= (hdrsize + pad + 8))) { |
1233 | /* | 1100 | /* XXX Need to generate an error CQ entry. */ |
1234 | * XXX Need to generate an error CQ | ||
1235 | * entry. | ||
1236 | */ | ||
1237 | goto ack_done; | 1101 | goto ack_done; |
1238 | } | 1102 | } |
1239 | tlen -= hdrsize + pad + 8; | 1103 | tlen -= hdrsize + pad + 8; |
1240 | if (unlikely(tlen != qp->s_len)) { | 1104 | if (unlikely(tlen != qp->s_len)) { |
1241 | /* | 1105 | /* XXX Need to generate an error CQ entry. */ |
1242 | * XXX Need to generate an error CQ | ||
1243 | * entry. | ||
1244 | */ | ||
1245 | goto ack_done; | 1106 | goto ack_done; |
1246 | } | 1107 | } |
1247 | if (!header_in_data) | 1108 | if (!header_in_data) |
@@ -1254,9 +1115,12 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, | |||
1254 | if (do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST))) { | 1115 | if (do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST))) { |
1255 | /* | 1116 | /* |
1256 | * Change the state so we contimue | 1117 | * Change the state so we contimue |
1257 | * processing new requests. | 1118 | * processing new requests and wake up the |
1119 | * tasklet if there are posted sends. | ||
1258 | */ | 1120 | */ |
1259 | qp->s_state = OP(SEND_LAST); | 1121 | qp->s_state = OP(SEND_LAST); |
1122 | if (qp->s_tail != qp->s_head) | ||
1123 | tasklet_hi_schedule(&qp->s_task); | ||
1260 | } | 1124 | } |
1261 | goto ack_done; | 1125 | goto ack_done; |
1262 | } | 1126 | } |
@@ -1302,18 +1166,16 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, | |||
1302 | * Don't queue the NAK if a RDMA read, atomic, or | 1166 | * Don't queue the NAK if a RDMA read, atomic, or |
1303 | * NAK is pending though. | 1167 | * NAK is pending though. |
1304 | */ | 1168 | */ |
1305 | spin_lock(&qp->s_lock); | 1169 | if (qp->s_ack_state != OP(ACKNOWLEDGE) || |
1306 | if ((qp->s_ack_state >= OP(RDMA_READ_REQUEST) && | 1170 | qp->r_nak_state != 0) |
1307 | qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) || | ||
1308 | qp->s_nak_state != 0) { | ||
1309 | spin_unlock(&qp->s_lock); | ||
1310 | goto done; | 1171 | goto done; |
1172 | if (qp->r_ack_state < OP(COMPARE_SWAP)) { | ||
1173 | qp->r_ack_state = OP(SEND_ONLY); | ||
1174 | qp->r_nak_state = IB_NAK_PSN_ERROR; | ||
1175 | /* Use the expected PSN. */ | ||
1176 | qp->r_ack_psn = qp->r_psn; | ||
1311 | } | 1177 | } |
1312 | qp->s_ack_state = OP(SEND_ONLY); | 1178 | goto send_ack; |
1313 | qp->s_nak_state = IB_NAK_PSN_ERROR; | ||
1314 | /* Use the expected PSN. */ | ||
1315 | qp->s_ack_psn = qp->r_psn; | ||
1316 | goto resched; | ||
1317 | } | 1179 | } |
1318 | 1180 | ||
1319 | /* | 1181 | /* |
@@ -1327,27 +1189,7 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, | |||
1327 | * send the earliest so that RDMA reads can be restarted at | 1189 | * send the earliest so that RDMA reads can be restarted at |
1328 | * the requester's expected PSN. | 1190 | * the requester's expected PSN. |
1329 | */ | 1191 | */ |
1330 | spin_lock(&qp->s_lock); | 1192 | if (opcode == OP(RDMA_READ_REQUEST)) { |
1331 | if (qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE && | ||
1332 | ipath_cmp24(psn, qp->s_ack_psn) >= 0) { | ||
1333 | if (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST) | ||
1334 | qp->s_ack_psn = psn; | ||
1335 | spin_unlock(&qp->s_lock); | ||
1336 | goto done; | ||
1337 | } | ||
1338 | switch (opcode) { | ||
1339 | case OP(RDMA_READ_REQUEST): | ||
1340 | /* | ||
1341 | * We have to be careful to not change s_rdma_sge | ||
1342 | * while ipath_do_rc_send() is using it and not | ||
1343 | * holding the s_lock. | ||
1344 | */ | ||
1345 | if (qp->s_ack_state != OP(ACKNOWLEDGE) && | ||
1346 | qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) { | ||
1347 | spin_unlock(&qp->s_lock); | ||
1348 | dev->n_rdma_dup_busy++; | ||
1349 | goto done; | ||
1350 | } | ||
1351 | /* RETH comes after BTH */ | 1193 | /* RETH comes after BTH */ |
1352 | if (!header_in_data) | 1194 | if (!header_in_data) |
1353 | reth = &ohdr->u.rc.reth; | 1195 | reth = &ohdr->u.rc.reth; |
@@ -1355,6 +1197,22 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, | |||
1355 | reth = (struct ib_reth *)data; | 1197 | reth = (struct ib_reth *)data; |
1356 | data += sizeof(*reth); | 1198 | data += sizeof(*reth); |
1357 | } | 1199 | } |
1200 | /* | ||
1201 | * If we receive a duplicate RDMA request, it means the | ||
1202 | * requester saw a sequence error and needs to restart | ||
1203 | * from an earlier point. We can abort the current | ||
1204 | * RDMA read send in that case. | ||
1205 | */ | ||
1206 | spin_lock_irq(&qp->s_lock); | ||
1207 | if (qp->s_ack_state != OP(ACKNOWLEDGE) && | ||
1208 | (qp->s_hdrwords || ipath_cmp24(psn, qp->s_ack_psn) >= 0)) { | ||
1209 | /* | ||
1210 | * We are already sending earlier requested data. | ||
1211 | * Don't abort it to send later out of sequence data. | ||
1212 | */ | ||
1213 | spin_unlock_irq(&qp->s_lock); | ||
1214 | goto done; | ||
1215 | } | ||
1358 | qp->s_rdma_len = be32_to_cpu(reth->length); | 1216 | qp->s_rdma_len = be32_to_cpu(reth->length); |
1359 | if (qp->s_rdma_len != 0) { | 1217 | if (qp->s_rdma_len != 0) { |
1360 | u32 rkey = be32_to_cpu(reth->rkey); | 1218 | u32 rkey = be32_to_cpu(reth->rkey); |
@@ -1368,8 +1226,10 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, | |||
1368 | ok = ipath_rkey_ok(dev, &qp->s_rdma_sge, | 1226 | ok = ipath_rkey_ok(dev, &qp->s_rdma_sge, |
1369 | qp->s_rdma_len, vaddr, rkey, | 1227 | qp->s_rdma_len, vaddr, rkey, |
1370 | IB_ACCESS_REMOTE_READ); | 1228 | IB_ACCESS_REMOTE_READ); |
1371 | if (unlikely(!ok)) | 1229 | if (unlikely(!ok)) { |
1230 | spin_unlock_irq(&qp->s_lock); | ||
1372 | goto done; | 1231 | goto done; |
1232 | } | ||
1373 | } else { | 1233 | } else { |
1374 | qp->s_rdma_sge.sg_list = NULL; | 1234 | qp->s_rdma_sge.sg_list = NULL; |
1375 | qp->s_rdma_sge.num_sge = 0; | 1235 | qp->s_rdma_sge.num_sge = 0; |
@@ -1378,25 +1238,44 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, | |||
1378 | qp->s_rdma_sge.sge.length = 0; | 1238 | qp->s_rdma_sge.sge.length = 0; |
1379 | qp->s_rdma_sge.sge.sge_length = 0; | 1239 | qp->s_rdma_sge.sge.sge_length = 0; |
1380 | } | 1240 | } |
1381 | break; | 1241 | qp->s_ack_state = opcode; |
1242 | qp->s_ack_psn = psn; | ||
1243 | spin_unlock_irq(&qp->s_lock); | ||
1244 | tasklet_hi_schedule(&qp->s_task); | ||
1245 | goto send_ack; | ||
1246 | } | ||
1247 | |||
1248 | /* | ||
1249 | * A pending RDMA read will ACK anything before it so | ||
1250 | * ignore earlier duplicate requests. | ||
1251 | */ | ||
1252 | if (qp->s_ack_state != OP(ACKNOWLEDGE)) | ||
1253 | goto done; | ||
1382 | 1254 | ||
1255 | /* | ||
1256 | * If an ACK is pending, don't replace the pending ACK | ||
1257 | * with an earlier one since the later one will ACK the earlier. | ||
1258 | * Also, if we already have a pending atomic, send it. | ||
1259 | */ | ||
1260 | if (qp->r_ack_state != OP(ACKNOWLEDGE) && | ||
1261 | (ipath_cmp24(psn, qp->r_ack_psn) <= 0 || | ||
1262 | qp->r_ack_state >= OP(COMPARE_SWAP))) | ||
1263 | goto send_ack; | ||
1264 | switch (opcode) { | ||
1383 | case OP(COMPARE_SWAP): | 1265 | case OP(COMPARE_SWAP): |
1384 | case OP(FETCH_ADD): | 1266 | case OP(FETCH_ADD): |
1385 | /* | 1267 | /* |
1386 | * Check for the PSN of the last atomic operations | 1268 | * Check for the PSN of the last atomic operation |
1387 | * performed and resend the result if found. | 1269 | * performed and resend the result if found. |
1388 | */ | 1270 | */ |
1389 | if ((psn & IPS_PSN_MASK) != qp->r_atomic_psn) { | 1271 | if ((psn & IPATH_PSN_MASK) != qp->r_atomic_psn) |
1390 | spin_unlock(&qp->s_lock); | ||
1391 | goto done; | 1272 | goto done; |
1392 | } | ||
1393 | qp->s_ack_atomic = qp->r_atomic_data; | ||
1394 | break; | 1273 | break; |
1395 | } | 1274 | } |
1396 | qp->s_ack_state = opcode; | 1275 | qp->r_ack_state = opcode; |
1397 | qp->s_nak_state = 0; | 1276 | qp->r_nak_state = 0; |
1398 | qp->s_ack_psn = psn; | 1277 | qp->r_ack_psn = psn; |
1399 | resched: | 1278 | send_ack: |
1400 | return 0; | 1279 | return 0; |
1401 | 1280 | ||
1402 | done: | 1281 | done: |
@@ -1424,7 +1303,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1424 | u32 hdrsize; | 1303 | u32 hdrsize; |
1425 | u32 psn; | 1304 | u32 psn; |
1426 | u32 pad; | 1305 | u32 pad; |
1427 | unsigned long flags; | ||
1428 | struct ib_wc wc; | 1306 | struct ib_wc wc; |
1429 | u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); | 1307 | u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); |
1430 | int diff; | 1308 | int diff; |
@@ -1453,11 +1331,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1453 | } else | 1331 | } else |
1454 | psn = be32_to_cpu(ohdr->bth[2]); | 1332 | psn = be32_to_cpu(ohdr->bth[2]); |
1455 | } | 1333 | } |
1456 | /* | ||
1457 | * The opcode is in the low byte when its in network order | ||
1458 | * (top byte when in host order). | ||
1459 | */ | ||
1460 | opcode = be32_to_cpu(ohdr->bth[0]) >> 24; | ||
1461 | 1334 | ||
1462 | /* | 1335 | /* |
1463 | * Process responses (ACKs) before anything else. Note that the | 1336 | * Process responses (ACKs) before anything else. Note that the |
@@ -1465,22 +1338,21 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1465 | * queue rather than the expected receive packet sequence number. | 1338 | * queue rather than the expected receive packet sequence number. |
1466 | * In other words, this QP is the requester. | 1339 | * In other words, this QP is the requester. |
1467 | */ | 1340 | */ |
1341 | opcode = be32_to_cpu(ohdr->bth[0]) >> 24; | ||
1468 | if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && | 1342 | if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) && |
1469 | opcode <= OP(ATOMIC_ACKNOWLEDGE)) { | 1343 | opcode <= OP(ATOMIC_ACKNOWLEDGE)) { |
1470 | ipath_rc_rcv_resp(dev, ohdr, data, tlen, qp, opcode, psn, | 1344 | ipath_rc_rcv_resp(dev, ohdr, data, tlen, qp, opcode, psn, |
1471 | hdrsize, pmtu, header_in_data); | 1345 | hdrsize, pmtu, header_in_data); |
1472 | goto bail; | 1346 | goto done; |
1473 | } | 1347 | } |
1474 | 1348 | ||
1475 | spin_lock_irqsave(&qp->r_rq.lock, flags); | ||
1476 | |||
1477 | /* Compute 24 bits worth of difference. */ | 1349 | /* Compute 24 bits worth of difference. */ |
1478 | diff = ipath_cmp24(psn, qp->r_psn); | 1350 | diff = ipath_cmp24(psn, qp->r_psn); |
1479 | if (unlikely(diff)) { | 1351 | if (unlikely(diff)) { |
1480 | if (ipath_rc_rcv_error(dev, ohdr, data, qp, opcode, | 1352 | if (ipath_rc_rcv_error(dev, ohdr, data, qp, opcode, |
1481 | psn, diff, header_in_data)) | 1353 | psn, diff, header_in_data)) |
1482 | goto done; | 1354 | goto done; |
1483 | goto resched; | 1355 | goto send_ack; |
1484 | } | 1356 | } |
1485 | 1357 | ||
1486 | /* Check for opcode sequence errors. */ | 1358 | /* Check for opcode sequence errors. */ |
@@ -1492,22 +1364,19 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1492 | opcode == OP(SEND_LAST_WITH_IMMEDIATE)) | 1364 | opcode == OP(SEND_LAST_WITH_IMMEDIATE)) |
1493 | break; | 1365 | break; |
1494 | nack_inv: | 1366 | nack_inv: |
1495 | /* | 1367 | /* |
1496 | * A NAK will ACK earlier sends and RDMA writes. Don't queue the | 1368 | * A NAK will ACK earlier sends and RDMA writes. |
1497 | * NAK if a RDMA read, atomic, or NAK is pending though. | 1369 | * Don't queue the NAK if a RDMA read, atomic, or NAK |
1498 | */ | 1370 | * is pending though. |
1499 | spin_lock(&qp->s_lock); | 1371 | */ |
1500 | if (qp->s_ack_state >= OP(RDMA_READ_REQUEST) && | 1372 | if (qp->r_ack_state >= OP(COMPARE_SWAP)) |
1501 | qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) { | 1373 | goto send_ack; |
1502 | spin_unlock(&qp->s_lock); | 1374 | /* XXX Flush WQEs */ |
1503 | goto done; | 1375 | qp->state = IB_QPS_ERR; |
1504 | } | 1376 | qp->r_ack_state = OP(SEND_ONLY); |
1505 | /* XXX Flush WQEs */ | 1377 | qp->r_nak_state = IB_NAK_INVALID_REQUEST; |
1506 | qp->state = IB_QPS_ERR; | 1378 | qp->r_ack_psn = qp->r_psn; |
1507 | qp->s_ack_state = OP(SEND_ONLY); | 1379 | goto send_ack; |
1508 | qp->s_nak_state = IB_NAK_INVALID_REQUEST; | ||
1509 | qp->s_ack_psn = qp->r_psn; | ||
1510 | goto resched; | ||
1511 | 1380 | ||
1512 | case OP(RDMA_WRITE_FIRST): | 1381 | case OP(RDMA_WRITE_FIRST): |
1513 | case OP(RDMA_WRITE_MIDDLE): | 1382 | case OP(RDMA_WRITE_MIDDLE): |
@@ -1517,20 +1386,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1517 | break; | 1386 | break; |
1518 | goto nack_inv; | 1387 | goto nack_inv; |
1519 | 1388 | ||
1520 | case OP(RDMA_READ_REQUEST): | ||
1521 | case OP(COMPARE_SWAP): | ||
1522 | case OP(FETCH_ADD): | ||
1523 | /* | ||
1524 | * Drop all new requests until a response has been sent. A | ||
1525 | * new request then ACKs the RDMA response we sent. Relaxed | ||
1526 | * ordering would allow new requests to be processed but we | ||
1527 | * would need to keep a queue of rwqe's for all that are in | ||
1528 | * progress. Note that we can't RNR NAK this request since | ||
1529 | * the RDMA READ or atomic response is already queued to be | ||
1530 | * sent (unless we implement a response send queue). | ||
1531 | */ | ||
1532 | goto done; | ||
1533 | |||
1534 | default: | 1389 | default: |
1535 | if (opcode == OP(SEND_MIDDLE) || | 1390 | if (opcode == OP(SEND_MIDDLE) || |
1536 | opcode == OP(SEND_LAST) || | 1391 | opcode == OP(SEND_LAST) || |
@@ -1539,6 +1394,11 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1539 | opcode == OP(RDMA_WRITE_LAST) || | 1394 | opcode == OP(RDMA_WRITE_LAST) || |
1540 | opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) | 1395 | opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE)) |
1541 | goto nack_inv; | 1396 | goto nack_inv; |
1397 | /* | ||
1398 | * Note that it is up to the requester to not send a new | ||
1399 | * RDMA read or atomic operation before receiving an ACK | ||
1400 | * for the previous operation. | ||
1401 | */ | ||
1542 | break; | 1402 | break; |
1543 | } | 1403 | } |
1544 | 1404 | ||
@@ -1555,17 +1415,12 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1555 | * Don't queue the NAK if a RDMA read or atomic | 1415 | * Don't queue the NAK if a RDMA read or atomic |
1556 | * is pending though. | 1416 | * is pending though. |
1557 | */ | 1417 | */ |
1558 | spin_lock(&qp->s_lock); | 1418 | if (qp->r_ack_state >= OP(COMPARE_SWAP)) |
1559 | if (qp->s_ack_state >= | 1419 | goto send_ack; |
1560 | OP(RDMA_READ_REQUEST) && | 1420 | qp->r_ack_state = OP(SEND_ONLY); |
1561 | qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) { | 1421 | qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer; |
1562 | spin_unlock(&qp->s_lock); | 1422 | qp->r_ack_psn = qp->r_psn; |
1563 | goto done; | 1423 | goto send_ack; |
1564 | } | ||
1565 | qp->s_ack_state = OP(SEND_ONLY); | ||
1566 | qp->s_nak_state = IB_RNR_NAK | qp->s_min_rnr_timer; | ||
1567 | qp->s_ack_psn = qp->r_psn; | ||
1568 | goto resched; | ||
1569 | } | 1424 | } |
1570 | qp->r_rcv_len = 0; | 1425 | qp->r_rcv_len = 0; |
1571 | /* FALLTHROUGH */ | 1426 | /* FALLTHROUGH */ |
@@ -1622,7 +1477,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1622 | if (unlikely(wc.byte_len > qp->r_len)) | 1477 | if (unlikely(wc.byte_len > qp->r_len)) |
1623 | goto nack_inv; | 1478 | goto nack_inv; |
1624 | ipath_copy_sge(&qp->r_sge, data, tlen); | 1479 | ipath_copy_sge(&qp->r_sge, data, tlen); |
1625 | atomic_inc(&qp->msn); | 1480 | qp->r_msn++; |
1626 | if (opcode == OP(RDMA_WRITE_LAST) || | 1481 | if (opcode == OP(RDMA_WRITE_LAST) || |
1627 | opcode == OP(RDMA_WRITE_ONLY)) | 1482 | opcode == OP(RDMA_WRITE_ONLY)) |
1628 | break; | 1483 | break; |
@@ -1666,29 +1521,8 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1666 | ok = ipath_rkey_ok(dev, &qp->r_sge, | 1521 | ok = ipath_rkey_ok(dev, &qp->r_sge, |
1667 | qp->r_len, vaddr, rkey, | 1522 | qp->r_len, vaddr, rkey, |
1668 | IB_ACCESS_REMOTE_WRITE); | 1523 | IB_ACCESS_REMOTE_WRITE); |
1669 | if (unlikely(!ok)) { | 1524 | if (unlikely(!ok)) |
1670 | nack_acc: | 1525 | goto nack_acc; |
1671 | /* | ||
1672 | * A NAK will ACK earlier sends and RDMA | ||
1673 | * writes. Don't queue the NAK if a RDMA | ||
1674 | * read, atomic, or NAK is pending though. | ||
1675 | */ | ||
1676 | spin_lock(&qp->s_lock); | ||
1677 | if (qp->s_ack_state >= | ||
1678 | OP(RDMA_READ_REQUEST) && | ||
1679 | qp->s_ack_state != | ||
1680 | IB_OPCODE_ACKNOWLEDGE) { | ||
1681 | spin_unlock(&qp->s_lock); | ||
1682 | goto done; | ||
1683 | } | ||
1684 | /* XXX Flush WQEs */ | ||
1685 | qp->state = IB_QPS_ERR; | ||
1686 | qp->s_ack_state = OP(RDMA_WRITE_ONLY); | ||
1687 | qp->s_nak_state = | ||
1688 | IB_NAK_REMOTE_ACCESS_ERROR; | ||
1689 | qp->s_ack_psn = qp->r_psn; | ||
1690 | goto resched; | ||
1691 | } | ||
1692 | } else { | 1526 | } else { |
1693 | qp->r_sge.sg_list = NULL; | 1527 | qp->r_sge.sg_list = NULL; |
1694 | qp->r_sge.sge.mr = NULL; | 1528 | qp->r_sge.sge.mr = NULL; |
@@ -1715,12 +1549,10 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1715 | reth = (struct ib_reth *)data; | 1549 | reth = (struct ib_reth *)data; |
1716 | data += sizeof(*reth); | 1550 | data += sizeof(*reth); |
1717 | } | 1551 | } |
1718 | spin_lock(&qp->s_lock); | 1552 | if (unlikely(!(qp->qp_access_flags & |
1719 | if (qp->s_ack_state != OP(ACKNOWLEDGE) && | 1553 | IB_ACCESS_REMOTE_READ))) |
1720 | qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) { | 1554 | goto nack_acc; |
1721 | spin_unlock(&qp->s_lock); | 1555 | spin_lock_irq(&qp->s_lock); |
1722 | goto done; | ||
1723 | } | ||
1724 | qp->s_rdma_len = be32_to_cpu(reth->length); | 1556 | qp->s_rdma_len = be32_to_cpu(reth->length); |
1725 | if (qp->s_rdma_len != 0) { | 1557 | if (qp->s_rdma_len != 0) { |
1726 | u32 rkey = be32_to_cpu(reth->rkey); | 1558 | u32 rkey = be32_to_cpu(reth->rkey); |
@@ -1732,7 +1564,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1732 | qp->s_rdma_len, vaddr, rkey, | 1564 | qp->s_rdma_len, vaddr, rkey, |
1733 | IB_ACCESS_REMOTE_READ); | 1565 | IB_ACCESS_REMOTE_READ); |
1734 | if (unlikely(!ok)) { | 1566 | if (unlikely(!ok)) { |
1735 | spin_unlock(&qp->s_lock); | 1567 | spin_unlock_irq(&qp->s_lock); |
1736 | goto nack_acc; | 1568 | goto nack_acc; |
1737 | } | 1569 | } |
1738 | /* | 1570 | /* |
@@ -1749,21 +1581,25 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1749 | qp->s_rdma_sge.sge.length = 0; | 1581 | qp->s_rdma_sge.sge.length = 0; |
1750 | qp->s_rdma_sge.sge.sge_length = 0; | 1582 | qp->s_rdma_sge.sge.sge_length = 0; |
1751 | } | 1583 | } |
1752 | if (unlikely(!(qp->qp_access_flags & | ||
1753 | IB_ACCESS_REMOTE_READ))) | ||
1754 | goto nack_acc; | ||
1755 | /* | 1584 | /* |
1756 | * We need to increment the MSN here instead of when we | 1585 | * We need to increment the MSN here instead of when we |
1757 | * finish sending the result since a duplicate request would | 1586 | * finish sending the result since a duplicate request would |
1758 | * increment it more than once. | 1587 | * increment it more than once. |
1759 | */ | 1588 | */ |
1760 | atomic_inc(&qp->msn); | 1589 | qp->r_msn++; |
1590 | |||
1761 | qp->s_ack_state = opcode; | 1591 | qp->s_ack_state = opcode; |
1762 | qp->s_nak_state = 0; | ||
1763 | qp->s_ack_psn = psn; | 1592 | qp->s_ack_psn = psn; |
1593 | spin_unlock_irq(&qp->s_lock); | ||
1594 | |||
1764 | qp->r_psn++; | 1595 | qp->r_psn++; |
1765 | qp->r_state = opcode; | 1596 | qp->r_state = opcode; |
1766 | goto rdmadone; | 1597 | qp->r_nak_state = 0; |
1598 | |||
1599 | /* Call ipath_do_rc_send() in another thread. */ | ||
1600 | tasklet_hi_schedule(&qp->s_task); | ||
1601 | |||
1602 | goto done; | ||
1767 | 1603 | ||
1768 | case OP(COMPARE_SWAP): | 1604 | case OP(COMPARE_SWAP): |
1769 | case OP(FETCH_ADD): { | 1605 | case OP(FETCH_ADD): { |
@@ -1792,7 +1628,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1792 | goto nack_acc; | 1628 | goto nack_acc; |
1793 | /* Perform atomic OP and save result. */ | 1629 | /* Perform atomic OP and save result. */ |
1794 | sdata = be64_to_cpu(ateth->swap_data); | 1630 | sdata = be64_to_cpu(ateth->swap_data); |
1795 | spin_lock(&dev->pending_lock); | 1631 | spin_lock_irq(&dev->pending_lock); |
1796 | qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr; | 1632 | qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr; |
1797 | if (opcode == OP(FETCH_ADD)) | 1633 | if (opcode == OP(FETCH_ADD)) |
1798 | *(u64 *) qp->r_sge.sge.vaddr = | 1634 | *(u64 *) qp->r_sge.sge.vaddr = |
@@ -1800,9 +1636,9 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1800 | else if (qp->r_atomic_data == | 1636 | else if (qp->r_atomic_data == |
1801 | be64_to_cpu(ateth->compare_data)) | 1637 | be64_to_cpu(ateth->compare_data)) |
1802 | *(u64 *) qp->r_sge.sge.vaddr = sdata; | 1638 | *(u64 *) qp->r_sge.sge.vaddr = sdata; |
1803 | spin_unlock(&dev->pending_lock); | 1639 | spin_unlock_irq(&dev->pending_lock); |
1804 | atomic_inc(&qp->msn); | 1640 | qp->r_msn++; |
1805 | qp->r_atomic_psn = psn & IPS_PSN_MASK; | 1641 | qp->r_atomic_psn = psn & IPATH_PSN_MASK; |
1806 | psn |= 1 << 31; | 1642 | psn |= 1 << 31; |
1807 | break; | 1643 | break; |
1808 | } | 1644 | } |
@@ -1813,44 +1649,39 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1813 | } | 1649 | } |
1814 | qp->r_psn++; | 1650 | qp->r_psn++; |
1815 | qp->r_state = opcode; | 1651 | qp->r_state = opcode; |
1652 | qp->r_nak_state = 0; | ||
1816 | /* Send an ACK if requested or required. */ | 1653 | /* Send an ACK if requested or required. */ |
1817 | if (psn & (1 << 31)) { | 1654 | if (psn & (1 << 31)) { |
1818 | /* | 1655 | /* |
1819 | * Coalesce ACKs unless there is a RDMA READ or | 1656 | * Coalesce ACKs unless there is a RDMA READ or |
1820 | * ATOMIC pending. | 1657 | * ATOMIC pending. |
1821 | */ | 1658 | */ |
1822 | spin_lock(&qp->s_lock); | 1659 | if (qp->r_ack_state < OP(COMPARE_SWAP)) { |
1823 | if (qp->s_ack_state == OP(ACKNOWLEDGE) || | 1660 | qp->r_ack_state = opcode; |
1824 | qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST) { | 1661 | qp->r_ack_psn = psn; |
1825 | qp->s_ack_state = opcode; | ||
1826 | qp->s_nak_state = 0; | ||
1827 | qp->s_ack_psn = psn; | ||
1828 | qp->s_ack_atomic = qp->r_atomic_data; | ||
1829 | goto resched; | ||
1830 | } | 1662 | } |
1831 | spin_unlock(&qp->s_lock); | 1663 | goto send_ack; |
1832 | } | 1664 | } |
1833 | done: | 1665 | goto done; |
1834 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
1835 | goto bail; | ||
1836 | 1666 | ||
1837 | resched: | 1667 | nack_acc: |
1838 | /* | 1668 | /* |
1839 | * Try to send ACK right away but not if ipath_do_rc_send() is | 1669 | * A NAK will ACK earlier sends and RDMA writes. |
1840 | * active. | 1670 | * Don't queue the NAK if a RDMA read, atomic, or NAK |
1671 | * is pending though. | ||
1841 | */ | 1672 | */ |
1842 | if (qp->s_hdrwords == 0 && | 1673 | if (qp->r_ack_state < OP(COMPARE_SWAP)) { |
1843 | (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST || | 1674 | /* XXX Flush WQEs */ |
1844 | qp->s_ack_state >= IB_OPCODE_COMPARE_SWAP)) | 1675 | qp->state = IB_QPS_ERR; |
1676 | qp->r_ack_state = OP(RDMA_WRITE_ONLY); | ||
1677 | qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; | ||
1678 | qp->r_ack_psn = qp->r_psn; | ||
1679 | } | ||
1680 | send_ack: | ||
1681 | /* Send ACK right away unless the send tasklet has a pending ACK. */ | ||
1682 | if (qp->s_ack_state == OP(ACKNOWLEDGE)) | ||
1845 | send_rc_ack(qp); | 1683 | send_rc_ack(qp); |
1846 | 1684 | ||
1847 | rdmadone: | 1685 | done: |
1848 | spin_unlock(&qp->s_lock); | ||
1849 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
1850 | |||
1851 | /* Call ipath_do_rc_send() in another thread. */ | ||
1852 | tasklet_hi_schedule(&qp->s_task); | ||
1853 | |||
1854 | bail: | ||
1855 | return; | 1686 | return; |
1856 | } | 1687 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h index 402126eb79c9..89df8f5ea998 100644 --- a/drivers/infiniband/hw/ipath/ipath_registers.h +++ b/drivers/infiniband/hw/ipath/ipath_registers.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index d38f4f3cfd1d..772bc59fb85c 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -31,6 +32,7 @@ | |||
31 | */ | 32 | */ |
32 | 33 | ||
33 | #include "ipath_verbs.h" | 34 | #include "ipath_verbs.h" |
35 | #include "ipath_common.h" | ||
34 | 36 | ||
35 | /* | 37 | /* |
36 | * Convert the AETH RNR timeout code into the number of milliseconds. | 38 | * Convert the AETH RNR timeout code into the number of milliseconds. |
@@ -111,20 +113,23 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp) | |||
111 | * | 113 | * |
112 | * Return 0 if no RWQE is available, otherwise return 1. | 114 | * Return 0 if no RWQE is available, otherwise return 1. |
113 | * | 115 | * |
114 | * Called at interrupt level with the QP r_rq.lock held. | 116 | * Can be called from interrupt level. |
115 | */ | 117 | */ |
116 | int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) | 118 | int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) |
117 | { | 119 | { |
120 | unsigned long flags; | ||
118 | struct ipath_rq *rq; | 121 | struct ipath_rq *rq; |
119 | struct ipath_srq *srq; | 122 | struct ipath_srq *srq; |
120 | struct ipath_rwqe *wqe; | 123 | struct ipath_rwqe *wqe; |
121 | int ret; | 124 | int ret = 1; |
122 | 125 | ||
123 | if (!qp->ibqp.srq) { | 126 | if (!qp->ibqp.srq) { |
124 | rq = &qp->r_rq; | 127 | rq = &qp->r_rq; |
128 | spin_lock_irqsave(&rq->lock, flags); | ||
129 | |||
125 | if (unlikely(rq->tail == rq->head)) { | 130 | if (unlikely(rq->tail == rq->head)) { |
126 | ret = 0; | 131 | ret = 0; |
127 | goto bail; | 132 | goto done; |
128 | } | 133 | } |
129 | wqe = get_rwqe_ptr(rq, rq->tail); | 134 | wqe = get_rwqe_ptr(rq, rq->tail); |
130 | qp->r_wr_id = wqe->wr_id; | 135 | qp->r_wr_id = wqe->wr_id; |
@@ -136,17 +141,16 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) | |||
136 | } | 141 | } |
137 | if (++rq->tail >= rq->size) | 142 | if (++rq->tail >= rq->size) |
138 | rq->tail = 0; | 143 | rq->tail = 0; |
139 | ret = 1; | 144 | goto done; |
140 | goto bail; | ||
141 | } | 145 | } |
142 | 146 | ||
143 | srq = to_isrq(qp->ibqp.srq); | 147 | srq = to_isrq(qp->ibqp.srq); |
144 | rq = &srq->rq; | 148 | rq = &srq->rq; |
145 | spin_lock(&rq->lock); | 149 | spin_lock_irqsave(&rq->lock, flags); |
150 | |||
146 | if (unlikely(rq->tail == rq->head)) { | 151 | if (unlikely(rq->tail == rq->head)) { |
147 | spin_unlock(&rq->lock); | ||
148 | ret = 0; | 152 | ret = 0; |
149 | goto bail; | 153 | goto done; |
150 | } | 154 | } |
151 | wqe = get_rwqe_ptr(rq, rq->tail); | 155 | wqe = get_rwqe_ptr(rq, rq->tail); |
152 | qp->r_wr_id = wqe->wr_id; | 156 | qp->r_wr_id = wqe->wr_id; |
@@ -168,18 +172,18 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) | |||
168 | n = rq->head - rq->tail; | 172 | n = rq->head - rq->tail; |
169 | if (n < srq->limit) { | 173 | if (n < srq->limit) { |
170 | srq->limit = 0; | 174 | srq->limit = 0; |
171 | spin_unlock(&rq->lock); | 175 | spin_unlock_irqrestore(&rq->lock, flags); |
172 | ev.device = qp->ibqp.device; | 176 | ev.device = qp->ibqp.device; |
173 | ev.element.srq = qp->ibqp.srq; | 177 | ev.element.srq = qp->ibqp.srq; |
174 | ev.event = IB_EVENT_SRQ_LIMIT_REACHED; | 178 | ev.event = IB_EVENT_SRQ_LIMIT_REACHED; |
175 | srq->ibsrq.event_handler(&ev, | 179 | srq->ibsrq.event_handler(&ev, |
176 | srq->ibsrq.srq_context); | 180 | srq->ibsrq.srq_context); |
177 | } else | 181 | goto bail; |
178 | spin_unlock(&rq->lock); | 182 | } |
179 | } else | 183 | } |
180 | spin_unlock(&rq->lock); | ||
181 | ret = 1; | ||
182 | 184 | ||
185 | done: | ||
186 | spin_unlock_irqrestore(&rq->lock, flags); | ||
183 | bail: | 187 | bail: |
184 | return ret; | 188 | return ret; |
185 | } | 189 | } |
@@ -187,7 +191,6 @@ bail: | |||
187 | /** | 191 | /** |
188 | * ipath_ruc_loopback - handle UC and RC lookback requests | 192 | * ipath_ruc_loopback - handle UC and RC lookback requests |
189 | * @sqp: the loopback QP | 193 | * @sqp: the loopback QP |
190 | * @wc: the work completion entry | ||
191 | * | 194 | * |
192 | * This is called from ipath_do_uc_send() or ipath_do_rc_send() to | 195 | * This is called from ipath_do_uc_send() or ipath_do_rc_send() to |
193 | * forward a WQE addressed to the same HCA. | 196 | * forward a WQE addressed to the same HCA. |
@@ -196,13 +199,14 @@ bail: | |||
196 | * receive interrupts since this is a connected protocol and all packets | 199 | * receive interrupts since this is a connected protocol and all packets |
197 | * will pass through here. | 200 | * will pass through here. |
198 | */ | 201 | */ |
199 | void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc) | 202 | static void ipath_ruc_loopback(struct ipath_qp *sqp) |
200 | { | 203 | { |
201 | struct ipath_ibdev *dev = to_idev(sqp->ibqp.device); | 204 | struct ipath_ibdev *dev = to_idev(sqp->ibqp.device); |
202 | struct ipath_qp *qp; | 205 | struct ipath_qp *qp; |
203 | struct ipath_swqe *wqe; | 206 | struct ipath_swqe *wqe; |
204 | struct ipath_sge *sge; | 207 | struct ipath_sge *sge; |
205 | unsigned long flags; | 208 | unsigned long flags; |
209 | struct ib_wc wc; | ||
206 | u64 sdata; | 210 | u64 sdata; |
207 | 211 | ||
208 | qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn); | 212 | qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn); |
@@ -233,8 +237,8 @@ again: | |||
233 | wqe = get_swqe_ptr(sqp, sqp->s_last); | 237 | wqe = get_swqe_ptr(sqp, sqp->s_last); |
234 | spin_unlock_irqrestore(&sqp->s_lock, flags); | 238 | spin_unlock_irqrestore(&sqp->s_lock, flags); |
235 | 239 | ||
236 | wc->wc_flags = 0; | 240 | wc.wc_flags = 0; |
237 | wc->imm_data = 0; | 241 | wc.imm_data = 0; |
238 | 242 | ||
239 | sqp->s_sge.sge = wqe->sg_list[0]; | 243 | sqp->s_sge.sge = wqe->sg_list[0]; |
240 | sqp->s_sge.sg_list = wqe->sg_list + 1; | 244 | sqp->s_sge.sg_list = wqe->sg_list + 1; |
@@ -242,39 +246,34 @@ again: | |||
242 | sqp->s_len = wqe->length; | 246 | sqp->s_len = wqe->length; |
243 | switch (wqe->wr.opcode) { | 247 | switch (wqe->wr.opcode) { |
244 | case IB_WR_SEND_WITH_IMM: | 248 | case IB_WR_SEND_WITH_IMM: |
245 | wc->wc_flags = IB_WC_WITH_IMM; | 249 | wc.wc_flags = IB_WC_WITH_IMM; |
246 | wc->imm_data = wqe->wr.imm_data; | 250 | wc.imm_data = wqe->wr.imm_data; |
247 | /* FALLTHROUGH */ | 251 | /* FALLTHROUGH */ |
248 | case IB_WR_SEND: | 252 | case IB_WR_SEND: |
249 | spin_lock_irqsave(&qp->r_rq.lock, flags); | ||
250 | if (!ipath_get_rwqe(qp, 0)) { | 253 | if (!ipath_get_rwqe(qp, 0)) { |
251 | rnr_nak: | 254 | rnr_nak: |
252 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
253 | /* Handle RNR NAK */ | 255 | /* Handle RNR NAK */ |
254 | if (qp->ibqp.qp_type == IB_QPT_UC) | 256 | if (qp->ibqp.qp_type == IB_QPT_UC) |
255 | goto send_comp; | 257 | goto send_comp; |
256 | if (sqp->s_rnr_retry == 0) { | 258 | if (sqp->s_rnr_retry == 0) { |
257 | wc->status = IB_WC_RNR_RETRY_EXC_ERR; | 259 | wc.status = IB_WC_RNR_RETRY_EXC_ERR; |
258 | goto err; | 260 | goto err; |
259 | } | 261 | } |
260 | if (sqp->s_rnr_retry_cnt < 7) | 262 | if (sqp->s_rnr_retry_cnt < 7) |
261 | sqp->s_rnr_retry--; | 263 | sqp->s_rnr_retry--; |
262 | dev->n_rnr_naks++; | 264 | dev->n_rnr_naks++; |
263 | sqp->s_rnr_timeout = | 265 | sqp->s_rnr_timeout = |
264 | ib_ipath_rnr_table[sqp->s_min_rnr_timer]; | 266 | ib_ipath_rnr_table[sqp->r_min_rnr_timer]; |
265 | ipath_insert_rnr_queue(sqp); | 267 | ipath_insert_rnr_queue(sqp); |
266 | goto done; | 268 | goto done; |
267 | } | 269 | } |
268 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
269 | break; | 270 | break; |
270 | 271 | ||
271 | case IB_WR_RDMA_WRITE_WITH_IMM: | 272 | case IB_WR_RDMA_WRITE_WITH_IMM: |
272 | wc->wc_flags = IB_WC_WITH_IMM; | 273 | wc.wc_flags = IB_WC_WITH_IMM; |
273 | wc->imm_data = wqe->wr.imm_data; | 274 | wc.imm_data = wqe->wr.imm_data; |
274 | spin_lock_irqsave(&qp->r_rq.lock, flags); | ||
275 | if (!ipath_get_rwqe(qp, 1)) | 275 | if (!ipath_get_rwqe(qp, 1)) |
276 | goto rnr_nak; | 276 | goto rnr_nak; |
277 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
278 | /* FALLTHROUGH */ | 277 | /* FALLTHROUGH */ |
279 | case IB_WR_RDMA_WRITE: | 278 | case IB_WR_RDMA_WRITE: |
280 | if (wqe->length == 0) | 279 | if (wqe->length == 0) |
@@ -284,20 +283,20 @@ again: | |||
284 | wqe->wr.wr.rdma.rkey, | 283 | wqe->wr.wr.rdma.rkey, |
285 | IB_ACCESS_REMOTE_WRITE))) { | 284 | IB_ACCESS_REMOTE_WRITE))) { |
286 | acc_err: | 285 | acc_err: |
287 | wc->status = IB_WC_REM_ACCESS_ERR; | 286 | wc.status = IB_WC_REM_ACCESS_ERR; |
288 | err: | 287 | err: |
289 | wc->wr_id = wqe->wr.wr_id; | 288 | wc.wr_id = wqe->wr.wr_id; |
290 | wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 289 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
291 | wc->vendor_err = 0; | 290 | wc.vendor_err = 0; |
292 | wc->byte_len = 0; | 291 | wc.byte_len = 0; |
293 | wc->qp_num = sqp->ibqp.qp_num; | 292 | wc.qp_num = sqp->ibqp.qp_num; |
294 | wc->src_qp = sqp->remote_qpn; | 293 | wc.src_qp = sqp->remote_qpn; |
295 | wc->pkey_index = 0; | 294 | wc.pkey_index = 0; |
296 | wc->slid = sqp->remote_ah_attr.dlid; | 295 | wc.slid = sqp->remote_ah_attr.dlid; |
297 | wc->sl = sqp->remote_ah_attr.sl; | 296 | wc.sl = sqp->remote_ah_attr.sl; |
298 | wc->dlid_path_bits = 0; | 297 | wc.dlid_path_bits = 0; |
299 | wc->port_num = 0; | 298 | wc.port_num = 0; |
300 | ipath_sqerror_qp(sqp, wc); | 299 | ipath_sqerror_qp(sqp, &wc); |
301 | goto done; | 300 | goto done; |
302 | } | 301 | } |
303 | break; | 302 | break; |
@@ -373,22 +372,22 @@ again: | |||
373 | goto send_comp; | 372 | goto send_comp; |
374 | 373 | ||
375 | if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM) | 374 | if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM) |
376 | wc->opcode = IB_WC_RECV_RDMA_WITH_IMM; | 375 | wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; |
377 | else | 376 | else |
378 | wc->opcode = IB_WC_RECV; | 377 | wc.opcode = IB_WC_RECV; |
379 | wc->wr_id = qp->r_wr_id; | 378 | wc.wr_id = qp->r_wr_id; |
380 | wc->status = IB_WC_SUCCESS; | 379 | wc.status = IB_WC_SUCCESS; |
381 | wc->vendor_err = 0; | 380 | wc.vendor_err = 0; |
382 | wc->byte_len = wqe->length; | 381 | wc.byte_len = wqe->length; |
383 | wc->qp_num = qp->ibqp.qp_num; | 382 | wc.qp_num = qp->ibqp.qp_num; |
384 | wc->src_qp = qp->remote_qpn; | 383 | wc.src_qp = qp->remote_qpn; |
385 | /* XXX do we know which pkey matched? Only needed for GSI. */ | 384 | /* XXX do we know which pkey matched? Only needed for GSI. */ |
386 | wc->pkey_index = 0; | 385 | wc.pkey_index = 0; |
387 | wc->slid = qp->remote_ah_attr.dlid; | 386 | wc.slid = qp->remote_ah_attr.dlid; |
388 | wc->sl = qp->remote_ah_attr.sl; | 387 | wc.sl = qp->remote_ah_attr.sl; |
389 | wc->dlid_path_bits = 0; | 388 | wc.dlid_path_bits = 0; |
390 | /* Signal completion event if the solicited bit is set. */ | 389 | /* Signal completion event if the solicited bit is set. */ |
391 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc, | 390 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, |
392 | wqe->wr.send_flags & IB_SEND_SOLICITED); | 391 | wqe->wr.send_flags & IB_SEND_SOLICITED); |
393 | 392 | ||
394 | send_comp: | 393 | send_comp: |
@@ -396,19 +395,19 @@ send_comp: | |||
396 | 395 | ||
397 | if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &sqp->s_flags) || | 396 | if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &sqp->s_flags) || |
398 | (wqe->wr.send_flags & IB_SEND_SIGNALED)) { | 397 | (wqe->wr.send_flags & IB_SEND_SIGNALED)) { |
399 | wc->wr_id = wqe->wr.wr_id; | 398 | wc.wr_id = wqe->wr.wr_id; |
400 | wc->status = IB_WC_SUCCESS; | 399 | wc.status = IB_WC_SUCCESS; |
401 | wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 400 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
402 | wc->vendor_err = 0; | 401 | wc.vendor_err = 0; |
403 | wc->byte_len = wqe->length; | 402 | wc.byte_len = wqe->length; |
404 | wc->qp_num = sqp->ibqp.qp_num; | 403 | wc.qp_num = sqp->ibqp.qp_num; |
405 | wc->src_qp = 0; | 404 | wc.src_qp = 0; |
406 | wc->pkey_index = 0; | 405 | wc.pkey_index = 0; |
407 | wc->slid = 0; | 406 | wc.slid = 0; |
408 | wc->sl = 0; | 407 | wc.sl = 0; |
409 | wc->dlid_path_bits = 0; | 408 | wc.dlid_path_bits = 0; |
410 | wc->port_num = 0; | 409 | wc.port_num = 0; |
411 | ipath_cq_enter(to_icq(sqp->ibqp.send_cq), wc, 0); | 410 | ipath_cq_enter(to_icq(sqp->ibqp.send_cq), &wc, 0); |
412 | } | 411 | } |
413 | 412 | ||
414 | /* Update s_last now that we are finished with the SWQE */ | 413 | /* Update s_last now that we are finished with the SWQE */ |
@@ -454,11 +453,11 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev) | |||
454 | } | 453 | } |
455 | 454 | ||
456 | /** | 455 | /** |
457 | * ipath_post_rc_send - post RC and UC sends | 456 | * ipath_post_ruc_send - post RC and UC sends |
458 | * @qp: the QP to post on | 457 | * @qp: the QP to post on |
459 | * @wr: the work request to send | 458 | * @wr: the work request to send |
460 | */ | 459 | */ |
461 | int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr) | 460 | int ipath_post_ruc_send(struct ipath_qp *qp, struct ib_send_wr *wr) |
462 | { | 461 | { |
463 | struct ipath_swqe *wqe; | 462 | struct ipath_swqe *wqe; |
464 | unsigned long flags; | 463 | unsigned long flags; |
@@ -533,13 +532,149 @@ int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
533 | qp->s_head = next; | 532 | qp->s_head = next; |
534 | spin_unlock_irqrestore(&qp->s_lock, flags); | 533 | spin_unlock_irqrestore(&qp->s_lock, flags); |
535 | 534 | ||
536 | if (qp->ibqp.qp_type == IB_QPT_UC) | 535 | ipath_do_ruc_send((unsigned long) qp); |
537 | ipath_do_uc_send((unsigned long) qp); | ||
538 | else | ||
539 | ipath_do_rc_send((unsigned long) qp); | ||
540 | 536 | ||
541 | ret = 0; | 537 | ret = 0; |
542 | 538 | ||
543 | bail: | 539 | bail: |
544 | return ret; | 540 | return ret; |
545 | } | 541 | } |
542 | |||
543 | /** | ||
544 | * ipath_make_grh - construct a GRH header | ||
545 | * @dev: a pointer to the ipath device | ||
546 | * @hdr: a pointer to the GRH header being constructed | ||
547 | * @grh: the global route address to send to | ||
548 | * @hwords: the number of 32 bit words of header being sent | ||
549 | * @nwords: the number of 32 bit words of data being sent | ||
550 | * | ||
551 | * Return the size of the header in 32 bit words. | ||
552 | */ | ||
553 | u32 ipath_make_grh(struct ipath_ibdev *dev, struct ib_grh *hdr, | ||
554 | struct ib_global_route *grh, u32 hwords, u32 nwords) | ||
555 | { | ||
556 | hdr->version_tclass_flow = | ||
557 | cpu_to_be32((6 << 28) | | ||
558 | (grh->traffic_class << 20) | | ||
559 | grh->flow_label); | ||
560 | hdr->paylen = cpu_to_be16((hwords - 2 + nwords + SIZE_OF_CRC) << 2); | ||
561 | /* next_hdr is defined by C8-7 in ch. 8.4.1 */ | ||
562 | hdr->next_hdr = 0x1B; | ||
563 | hdr->hop_limit = grh->hop_limit; | ||
564 | /* The SGID is 32-bit aligned. */ | ||
565 | hdr->sgid.global.subnet_prefix = dev->gid_prefix; | ||
566 | hdr->sgid.global.interface_id = ipath_layer_get_guid(dev->dd); | ||
567 | hdr->dgid = grh->dgid; | ||
568 | |||
569 | /* GRH header size in 32-bit words. */ | ||
570 | return sizeof(struct ib_grh) / sizeof(u32); | ||
571 | } | ||
572 | |||
573 | /** | ||
574 | * ipath_do_ruc_send - perform a send on an RC or UC QP | ||
575 | * @data: contains a pointer to the QP | ||
576 | * | ||
577 | * Process entries in the send work queue until credit or queue is | ||
578 | * exhausted. Only allow one CPU to send a packet per QP (tasklet). | ||
579 | * Otherwise, after we drop the QP s_lock, two threads could send | ||
580 | * packets out of order. | ||
581 | */ | ||
582 | void ipath_do_ruc_send(unsigned long data) | ||
583 | { | ||
584 | struct ipath_qp *qp = (struct ipath_qp *)data; | ||
585 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | ||
586 | unsigned long flags; | ||
587 | u16 lrh0; | ||
588 | u32 nwords; | ||
589 | u32 extra_bytes; | ||
590 | u32 bth0; | ||
591 | u32 bth2; | ||
592 | u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); | ||
593 | struct ipath_other_headers *ohdr; | ||
594 | |||
595 | if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags)) | ||
596 | goto bail; | ||
597 | |||
598 | if (unlikely(qp->remote_ah_attr.dlid == | ||
599 | ipath_layer_get_lid(dev->dd))) { | ||
600 | ipath_ruc_loopback(qp); | ||
601 | goto clear; | ||
602 | } | ||
603 | |||
604 | ohdr = &qp->s_hdr.u.oth; | ||
605 | if (qp->remote_ah_attr.ah_flags & IB_AH_GRH) | ||
606 | ohdr = &qp->s_hdr.u.l.oth; | ||
607 | |||
608 | again: | ||
609 | /* Check for a constructed packet to be sent. */ | ||
610 | if (qp->s_hdrwords != 0) { | ||
611 | /* | ||
612 | * If no PIO bufs are available, return. An interrupt will | ||
613 | * call ipath_ib_piobufavail() when one is available. | ||
614 | */ | ||
615 | if (ipath_verbs_send(dev->dd, qp->s_hdrwords, | ||
616 | (u32 *) &qp->s_hdr, qp->s_cur_size, | ||
617 | qp->s_cur_sge)) { | ||
618 | ipath_no_bufs_available(qp, dev); | ||
619 | goto bail; | ||
620 | } | ||
621 | dev->n_unicast_xmit++; | ||
622 | /* Record that we sent the packet and s_hdr is empty. */ | ||
623 | qp->s_hdrwords = 0; | ||
624 | } | ||
625 | |||
626 | /* | ||
627 | * The lock is needed to synchronize between setting | ||
628 | * qp->s_ack_state, resend timer, and post_send(). | ||
629 | */ | ||
630 | spin_lock_irqsave(&qp->s_lock, flags); | ||
631 | |||
632 | /* Sending responses has higher priority over sending requests. */ | ||
633 | if (qp->s_ack_state != IB_OPCODE_RC_ACKNOWLEDGE && | ||
634 | (bth0 = ipath_make_rc_ack(qp, ohdr, pmtu)) != 0) | ||
635 | bth2 = qp->s_ack_psn++ & IPATH_PSN_MASK; | ||
636 | else if (!((qp->ibqp.qp_type == IB_QPT_RC) ? | ||
637 | ipath_make_rc_req(qp, ohdr, pmtu, &bth0, &bth2) : | ||
638 | ipath_make_uc_req(qp, ohdr, pmtu, &bth0, &bth2))) { | ||
639 | /* | ||
640 | * Clear the busy bit before unlocking to avoid races with | ||
641 | * adding new work queue items and then failing to process | ||
642 | * them. | ||
643 | */ | ||
644 | clear_bit(IPATH_S_BUSY, &qp->s_flags); | ||
645 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
646 | goto bail; | ||
647 | } | ||
648 | |||
649 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
650 | |||
651 | /* Construct the header. */ | ||
652 | extra_bytes = (4 - qp->s_cur_size) & 3; | ||
653 | nwords = (qp->s_cur_size + extra_bytes) >> 2; | ||
654 | lrh0 = IPATH_LRH_BTH; | ||
655 | if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) { | ||
656 | qp->s_hdrwords += ipath_make_grh(dev, &qp->s_hdr.u.l.grh, | ||
657 | &qp->remote_ah_attr.grh, | ||
658 | qp->s_hdrwords, nwords); | ||
659 | lrh0 = IPATH_LRH_GRH; | ||
660 | } | ||
661 | lrh0 |= qp->remote_ah_attr.sl << 4; | ||
662 | qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); | ||
663 | qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); | ||
664 | qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + | ||
665 | SIZE_OF_CRC); | ||
666 | qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); | ||
667 | bth0 |= ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); | ||
668 | bth0 |= extra_bytes << 20; | ||
669 | ohdr->bth[0] = cpu_to_be32(bth0); | ||
670 | ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); | ||
671 | ohdr->bth[2] = cpu_to_be32(bth2); | ||
672 | |||
673 | /* Check for more work to do. */ | ||
674 | goto again; | ||
675 | |||
676 | clear: | ||
677 | clear_bit(IPATH_S_BUSY, &qp->s_flags); | ||
678 | bail: | ||
679 | return; | ||
680 | } | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c index 01c4c6c56118..f760434660bd 100644 --- a/drivers/infiniband/hw/ipath/ipath_srq.c +++ b/drivers/infiniband/hw/ipath/ipath_srq.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -125,11 +126,23 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, | |||
125 | struct ib_srq_init_attr *srq_init_attr, | 126 | struct ib_srq_init_attr *srq_init_attr, |
126 | struct ib_udata *udata) | 127 | struct ib_udata *udata) |
127 | { | 128 | { |
129 | struct ipath_ibdev *dev = to_idev(ibpd->device); | ||
128 | struct ipath_srq *srq; | 130 | struct ipath_srq *srq; |
129 | u32 sz; | 131 | u32 sz; |
130 | struct ib_srq *ret; | 132 | struct ib_srq *ret; |
131 | 133 | ||
132 | if (srq_init_attr->attr.max_sge < 1) { | 134 | if (dev->n_srqs_allocated == ib_ipath_max_srqs) { |
135 | ret = ERR_PTR(-ENOMEM); | ||
136 | goto bail; | ||
137 | } | ||
138 | |||
139 | if (srq_init_attr->attr.max_wr == 0) { | ||
140 | ret = ERR_PTR(-EINVAL); | ||
141 | goto bail; | ||
142 | } | ||
143 | |||
144 | if ((srq_init_attr->attr.max_sge > ib_ipath_max_srq_sges) || | ||
145 | (srq_init_attr->attr.max_wr > ib_ipath_max_srq_wrs)) { | ||
133 | ret = ERR_PTR(-EINVAL); | 146 | ret = ERR_PTR(-EINVAL); |
134 | goto bail; | 147 | goto bail; |
135 | } | 148 | } |
@@ -164,6 +177,8 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, | |||
164 | 177 | ||
165 | ret = &srq->ibsrq; | 178 | ret = &srq->ibsrq; |
166 | 179 | ||
180 | dev->n_srqs_allocated++; | ||
181 | |||
167 | bail: | 182 | bail: |
168 | return ret; | 183 | return ret; |
169 | } | 184 | } |
@@ -181,24 +196,26 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, | |||
181 | unsigned long flags; | 196 | unsigned long flags; |
182 | int ret; | 197 | int ret; |
183 | 198 | ||
184 | if (attr_mask & IB_SRQ_LIMIT) { | 199 | if (attr_mask & IB_SRQ_MAX_WR) |
185 | spin_lock_irqsave(&srq->rq.lock, flags); | 200 | if ((attr->max_wr > ib_ipath_max_srq_wrs) || |
186 | srq->limit = attr->srq_limit; | 201 | (attr->max_sge > srq->rq.max_sge)) { |
187 | spin_unlock_irqrestore(&srq->rq.lock, flags); | 202 | ret = -EINVAL; |
188 | } | 203 | goto bail; |
189 | if (attr_mask & IB_SRQ_MAX_WR) { | 204 | } |
190 | u32 size = attr->max_wr + 1; | ||
191 | struct ipath_rwqe *wq, *p; | ||
192 | u32 n; | ||
193 | u32 sz; | ||
194 | 205 | ||
195 | if (attr->max_sge < srq->rq.max_sge) { | 206 | if (attr_mask & IB_SRQ_LIMIT) |
207 | if (attr->srq_limit >= srq->rq.size) { | ||
196 | ret = -EINVAL; | 208 | ret = -EINVAL; |
197 | goto bail; | 209 | goto bail; |
198 | } | 210 | } |
199 | 211 | ||
212 | if (attr_mask & IB_SRQ_MAX_WR) { | ||
213 | struct ipath_rwqe *wq, *p; | ||
214 | u32 sz, size, n; | ||
215 | |||
200 | sz = sizeof(struct ipath_rwqe) + | 216 | sz = sizeof(struct ipath_rwqe) + |
201 | attr->max_sge * sizeof(struct ipath_sge); | 217 | attr->max_sge * sizeof(struct ipath_sge); |
218 | size = attr->max_wr + 1; | ||
202 | wq = vmalloc(size * sz); | 219 | wq = vmalloc(size * sz); |
203 | if (!wq) { | 220 | if (!wq) { |
204 | ret = -ENOMEM; | 221 | ret = -ENOMEM; |
@@ -242,6 +259,11 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, | |||
242 | spin_unlock_irqrestore(&srq->rq.lock, flags); | 259 | spin_unlock_irqrestore(&srq->rq.lock, flags); |
243 | } | 260 | } |
244 | 261 | ||
262 | if (attr_mask & IB_SRQ_LIMIT) { | ||
263 | spin_lock_irqsave(&srq->rq.lock, flags); | ||
264 | srq->limit = attr->srq_limit; | ||
265 | spin_unlock_irqrestore(&srq->rq.lock, flags); | ||
266 | } | ||
245 | ret = 0; | 267 | ret = 0; |
246 | 268 | ||
247 | bail: | 269 | bail: |
@@ -265,7 +287,9 @@ int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr) | |||
265 | int ipath_destroy_srq(struct ib_srq *ibsrq) | 287 | int ipath_destroy_srq(struct ib_srq *ibsrq) |
266 | { | 288 | { |
267 | struct ipath_srq *srq = to_isrq(ibsrq); | 289 | struct ipath_srq *srq = to_isrq(ibsrq); |
290 | struct ipath_ibdev *dev = to_idev(ibsrq->device); | ||
268 | 291 | ||
292 | dev->n_srqs_allocated--; | ||
269 | vfree(srq->rq.wq); | 293 | vfree(srq->rq.wq); |
270 | kfree(srq); | 294 | kfree(srq); |
271 | 295 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c index fe209137ee74..70351b7e35c0 100644 --- a/drivers/infiniband/hw/ipath/ipath_stats.c +++ b/drivers/infiniband/hw/ipath/ipath_stats.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -185,7 +186,6 @@ static void ipath_qcheck(struct ipath_devdata *dd) | |||
185 | dd->ipath_port0head, | 186 | dd->ipath_port0head, |
186 | (unsigned long long) | 187 | (unsigned long long) |
187 | ipath_stats.sps_port0pkts); | 188 | ipath_stats.sps_port0pkts); |
188 | ipath_kreceive(dd); | ||
189 | } | 189 | } |
190 | dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts; | 190 | dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts; |
191 | } | 191 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c index f323791cc495..b98821d7801d 100644 --- a/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -34,8 +35,8 @@ | |||
34 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
35 | 36 | ||
36 | #include "ipath_kernel.h" | 37 | #include "ipath_kernel.h" |
37 | #include "ips_common.h" | ||
38 | #include "ipath_layer.h" | 38 | #include "ipath_layer.h" |
39 | #include "ipath_common.h" | ||
39 | 40 | ||
40 | /** | 41 | /** |
41 | * ipath_parse_ushort - parse an unsigned short value in an arbitrary base | 42 | * ipath_parse_ushort - parse an unsigned short value in an arbitrary base |
@@ -84,99 +85,6 @@ static ssize_t show_num_units(struct device_driver *dev, char *buf) | |||
84 | ipath_count_units(NULL, NULL, NULL)); | 85 | ipath_count_units(NULL, NULL, NULL)); |
85 | } | 86 | } |
86 | 87 | ||
87 | #define DRIVER_STAT(name, attr) \ | ||
88 | static ssize_t show_stat_##name(struct device_driver *dev, \ | ||
89 | char *buf) \ | ||
90 | { \ | ||
91 | return scnprintf( \ | ||
92 | buf, PAGE_SIZE, "%llu\n", \ | ||
93 | (unsigned long long) ipath_stats.sps_ ##attr); \ | ||
94 | } \ | ||
95 | static DRIVER_ATTR(name, S_IRUGO, show_stat_##name, NULL) | ||
96 | |||
97 | DRIVER_STAT(intrs, ints); | ||
98 | DRIVER_STAT(err_intrs, errints); | ||
99 | DRIVER_STAT(errs, errs); | ||
100 | DRIVER_STAT(pkt_errs, pkterrs); | ||
101 | DRIVER_STAT(crc_errs, crcerrs); | ||
102 | DRIVER_STAT(hw_errs, hwerrs); | ||
103 | DRIVER_STAT(ib_link, iblink); | ||
104 | DRIVER_STAT(port0_pkts, port0pkts); | ||
105 | DRIVER_STAT(ether_spkts, ether_spkts); | ||
106 | DRIVER_STAT(ether_rpkts, ether_rpkts); | ||
107 | DRIVER_STAT(sma_spkts, sma_spkts); | ||
108 | DRIVER_STAT(sma_rpkts, sma_rpkts); | ||
109 | DRIVER_STAT(hdrq_full, hdrqfull); | ||
110 | DRIVER_STAT(etid_full, etidfull); | ||
111 | DRIVER_STAT(no_piobufs, nopiobufs); | ||
112 | DRIVER_STAT(ports, ports); | ||
113 | DRIVER_STAT(pkey0, pkeys[0]); | ||
114 | DRIVER_STAT(pkey1, pkeys[1]); | ||
115 | DRIVER_STAT(pkey2, pkeys[2]); | ||
116 | DRIVER_STAT(pkey3, pkeys[3]); | ||
117 | /* XXX fix the following when dynamic table of devices used */ | ||
118 | DRIVER_STAT(lid0, lid[0]); | ||
119 | DRIVER_STAT(lid1, lid[1]); | ||
120 | DRIVER_STAT(lid2, lid[2]); | ||
121 | DRIVER_STAT(lid3, lid[3]); | ||
122 | |||
123 | DRIVER_STAT(nports, nports); | ||
124 | DRIVER_STAT(null_intr, nullintr); | ||
125 | DRIVER_STAT(max_pkts_call, maxpkts_call); | ||
126 | DRIVER_STAT(avg_pkts_call, avgpkts_call); | ||
127 | DRIVER_STAT(page_locks, pagelocks); | ||
128 | DRIVER_STAT(page_unlocks, pageunlocks); | ||
129 | DRIVER_STAT(krdrops, krdrops); | ||
130 | /* XXX fix the following when dynamic table of devices used */ | ||
131 | DRIVER_STAT(mlid0, mlid[0]); | ||
132 | DRIVER_STAT(mlid1, mlid[1]); | ||
133 | DRIVER_STAT(mlid2, mlid[2]); | ||
134 | DRIVER_STAT(mlid3, mlid[3]); | ||
135 | |||
136 | static struct attribute *driver_stat_attributes[] = { | ||
137 | &driver_attr_intrs.attr, | ||
138 | &driver_attr_err_intrs.attr, | ||
139 | &driver_attr_errs.attr, | ||
140 | &driver_attr_pkt_errs.attr, | ||
141 | &driver_attr_crc_errs.attr, | ||
142 | &driver_attr_hw_errs.attr, | ||
143 | &driver_attr_ib_link.attr, | ||
144 | &driver_attr_port0_pkts.attr, | ||
145 | &driver_attr_ether_spkts.attr, | ||
146 | &driver_attr_ether_rpkts.attr, | ||
147 | &driver_attr_sma_spkts.attr, | ||
148 | &driver_attr_sma_rpkts.attr, | ||
149 | &driver_attr_hdrq_full.attr, | ||
150 | &driver_attr_etid_full.attr, | ||
151 | &driver_attr_no_piobufs.attr, | ||
152 | &driver_attr_ports.attr, | ||
153 | &driver_attr_pkey0.attr, | ||
154 | &driver_attr_pkey1.attr, | ||
155 | &driver_attr_pkey2.attr, | ||
156 | &driver_attr_pkey3.attr, | ||
157 | &driver_attr_lid0.attr, | ||
158 | &driver_attr_lid1.attr, | ||
159 | &driver_attr_lid2.attr, | ||
160 | &driver_attr_lid3.attr, | ||
161 | &driver_attr_nports.attr, | ||
162 | &driver_attr_null_intr.attr, | ||
163 | &driver_attr_max_pkts_call.attr, | ||
164 | &driver_attr_avg_pkts_call.attr, | ||
165 | &driver_attr_page_locks.attr, | ||
166 | &driver_attr_page_unlocks.attr, | ||
167 | &driver_attr_krdrops.attr, | ||
168 | &driver_attr_mlid0.attr, | ||
169 | &driver_attr_mlid1.attr, | ||
170 | &driver_attr_mlid2.attr, | ||
171 | &driver_attr_mlid3.attr, | ||
172 | NULL | ||
173 | }; | ||
174 | |||
175 | static struct attribute_group driver_stat_attr_group = { | ||
176 | .name = "stats", | ||
177 | .attrs = driver_stat_attributes | ||
178 | }; | ||
179 | |||
180 | static ssize_t show_status(struct device *dev, | 88 | static ssize_t show_status(struct device *dev, |
181 | struct device_attribute *attr, | 89 | struct device_attribute *attr, |
182 | char *buf) | 90 | char *buf) |
@@ -272,23 +180,23 @@ static ssize_t store_lid(struct device *dev, | |||
272 | size_t count) | 180 | size_t count) |
273 | { | 181 | { |
274 | struct ipath_devdata *dd = dev_get_drvdata(dev); | 182 | struct ipath_devdata *dd = dev_get_drvdata(dev); |
275 | u16 lid; | 183 | u16 lid = 0; |
276 | int ret; | 184 | int ret; |
277 | 185 | ||
278 | ret = ipath_parse_ushort(buf, &lid); | 186 | ret = ipath_parse_ushort(buf, &lid); |
279 | if (ret < 0) | 187 | if (ret < 0) |
280 | goto invalid; | 188 | goto invalid; |
281 | 189 | ||
282 | if (lid == 0 || lid >= 0xc000) { | 190 | if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) { |
283 | ret = -EINVAL; | 191 | ret = -EINVAL; |
284 | goto invalid; | 192 | goto invalid; |
285 | } | 193 | } |
286 | 194 | ||
287 | ipath_set_sps_lid(dd, lid, 0); | 195 | ipath_set_lid(dd, lid, 0); |
288 | 196 | ||
289 | goto bail; | 197 | goto bail; |
290 | invalid: | 198 | invalid: |
291 | ipath_dev_err(dd, "attempt to set invalid LID\n"); | 199 | ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid); |
292 | bail: | 200 | bail: |
293 | return ret; | 201 | return ret; |
294 | } | 202 | } |
@@ -313,13 +221,12 @@ static ssize_t store_mlid(struct device *dev, | |||
313 | int ret; | 221 | int ret; |
314 | 222 | ||
315 | ret = ipath_parse_ushort(buf, &mlid); | 223 | ret = ipath_parse_ushort(buf, &mlid); |
316 | if (ret < 0) | 224 | if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE) |
317 | goto invalid; | 225 | goto invalid; |
318 | 226 | ||
319 | unit = dd->ipath_unit; | 227 | unit = dd->ipath_unit; |
320 | 228 | ||
321 | dd->ipath_mlid = mlid; | 229 | dd->ipath_mlid = mlid; |
322 | ipath_stats.sps_mlid[unit] = mlid; | ||
323 | ipath_layer_intr(dd, IPATH_LAYER_INT_BCAST); | 230 | ipath_layer_intr(dd, IPATH_LAYER_INT_BCAST); |
324 | 231 | ||
325 | goto bail; | 232 | goto bail; |
@@ -734,20 +641,12 @@ int ipath_driver_create_group(struct device_driver *drv) | |||
734 | int ret; | 641 | int ret; |
735 | 642 | ||
736 | ret = sysfs_create_group(&drv->kobj, &driver_attr_group); | 643 | ret = sysfs_create_group(&drv->kobj, &driver_attr_group); |
737 | if (ret) | ||
738 | goto bail; | ||
739 | 644 | ||
740 | ret = sysfs_create_group(&drv->kobj, &driver_stat_attr_group); | ||
741 | if (ret) | ||
742 | sysfs_remove_group(&drv->kobj, &driver_attr_group); | ||
743 | |||
744 | bail: | ||
745 | return ret; | 645 | return ret; |
746 | } | 646 | } |
747 | 647 | ||
748 | void ipath_driver_remove_group(struct device_driver *drv) | 648 | void ipath_driver_remove_group(struct device_driver *drv) |
749 | { | 649 | { |
750 | sysfs_remove_group(&drv->kobj, &driver_stat_attr_group); | ||
751 | sysfs_remove_group(&drv->kobj, &driver_attr_group); | 650 | sysfs_remove_group(&drv->kobj, &driver_attr_group); |
752 | } | 651 | } |
753 | 652 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c index 0d6dbc0a541e..c33abea2d5a7 100644 --- a/drivers/infiniband/hw/ipath/ipath_uc.c +++ b/drivers/infiniband/hw/ipath/ipath_uc.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -31,7 +32,7 @@ | |||
31 | */ | 32 | */ |
32 | 33 | ||
33 | #include "ipath_verbs.h" | 34 | #include "ipath_verbs.h" |
34 | #include "ips_common.h" | 35 | #include "ipath_common.h" |
35 | 36 | ||
36 | /* cut down ridiculously long IB macro names */ | 37 | /* cut down ridiculously long IB macro names */ |
37 | #define OP(x) IB_OPCODE_UC_##x | 38 | #define OP(x) IB_OPCODE_UC_##x |
@@ -61,90 +62,40 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe, | |||
61 | } | 62 | } |
62 | 63 | ||
63 | /** | 64 | /** |
64 | * ipath_do_uc_send - do a send on a UC queue | 65 | * ipath_make_uc_req - construct a request packet (SEND, RDMA write) |
65 | * @data: contains a pointer to the QP to send on | 66 | * @qp: a pointer to the QP |
67 | * @ohdr: a pointer to the IB header being constructed | ||
68 | * @pmtu: the path MTU | ||
69 | * @bth0p: pointer to the BTH opcode word | ||
70 | * @bth2p: pointer to the BTH PSN word | ||
66 | * | 71 | * |
67 | * Process entries in the send work queue until the queue is exhausted. | 72 | * Return 1 if constructed; otherwise, return 0. |
68 | * Only allow one CPU to send a packet per QP (tasklet). | 73 | * Note the QP s_lock must be held and interrupts disabled. |
69 | * Otherwise, after we drop the QP lock, two threads could send | ||
70 | * packets out of order. | ||
71 | * This is similar to ipath_do_rc_send() below except we don't have | ||
72 | * timeouts or resends. | ||
73 | */ | 74 | */ |
74 | void ipath_do_uc_send(unsigned long data) | 75 | int ipath_make_uc_req(struct ipath_qp *qp, |
76 | struct ipath_other_headers *ohdr, | ||
77 | u32 pmtu, u32 *bth0p, u32 *bth2p) | ||
75 | { | 78 | { |
76 | struct ipath_qp *qp = (struct ipath_qp *)data; | ||
77 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | ||
78 | struct ipath_swqe *wqe; | 79 | struct ipath_swqe *wqe; |
79 | unsigned long flags; | ||
80 | u16 lrh0; | ||
81 | u32 hwords; | 80 | u32 hwords; |
82 | u32 nwords; | ||
83 | u32 extra_bytes; | ||
84 | u32 bth0; | 81 | u32 bth0; |
85 | u32 bth2; | ||
86 | u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); | ||
87 | u32 len; | 82 | u32 len; |
88 | struct ipath_other_headers *ohdr; | ||
89 | struct ib_wc wc; | 83 | struct ib_wc wc; |
90 | 84 | ||
91 | if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags)) | ||
92 | goto bail; | ||
93 | |||
94 | if (unlikely(qp->remote_ah_attr.dlid == | ||
95 | ipath_layer_get_lid(dev->dd))) { | ||
96 | /* Pass in an uninitialized ib_wc to save stack space. */ | ||
97 | ipath_ruc_loopback(qp, &wc); | ||
98 | clear_bit(IPATH_S_BUSY, &qp->s_flags); | ||
99 | goto bail; | ||
100 | } | ||
101 | |||
102 | ohdr = &qp->s_hdr.u.oth; | ||
103 | if (qp->remote_ah_attr.ah_flags & IB_AH_GRH) | ||
104 | ohdr = &qp->s_hdr.u.l.oth; | ||
105 | |||
106 | again: | ||
107 | /* Check for a constructed packet to be sent. */ | ||
108 | if (qp->s_hdrwords != 0) { | ||
109 | /* | ||
110 | * If no PIO bufs are available, return. | ||
111 | * An interrupt will call ipath_ib_piobufavail() | ||
112 | * when one is available. | ||
113 | */ | ||
114 | if (ipath_verbs_send(dev->dd, qp->s_hdrwords, | ||
115 | (u32 *) &qp->s_hdr, | ||
116 | qp->s_cur_size, | ||
117 | qp->s_cur_sge)) { | ||
118 | ipath_no_bufs_available(qp, dev); | ||
119 | goto bail; | ||
120 | } | ||
121 | dev->n_unicast_xmit++; | ||
122 | /* Record that we sent the packet and s_hdr is empty. */ | ||
123 | qp->s_hdrwords = 0; | ||
124 | } | ||
125 | |||
126 | lrh0 = IPS_LRH_BTH; | ||
127 | /* header size in 32-bit words LRH+BTH = (8+12)/4. */ | ||
128 | hwords = 5; | ||
129 | |||
130 | /* | ||
131 | * The lock is needed to synchronize between | ||
132 | * setting qp->s_ack_state and post_send(). | ||
133 | */ | ||
134 | spin_lock_irqsave(&qp->s_lock, flags); | ||
135 | |||
136 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) | 85 | if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) |
137 | goto done; | 86 | goto done; |
138 | 87 | ||
139 | bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); | 88 | /* header size in 32-bit words LRH+BTH = (8+12)/4. */ |
89 | hwords = 5; | ||
90 | bth0 = 0; | ||
140 | 91 | ||
141 | /* Send a request. */ | 92 | /* Get the next send request. */ |
142 | wqe = get_swqe_ptr(qp, qp->s_last); | 93 | wqe = get_swqe_ptr(qp, qp->s_last); |
143 | switch (qp->s_state) { | 94 | switch (qp->s_state) { |
144 | default: | 95 | default: |
145 | /* | 96 | /* |
146 | * Signal the completion of the last send (if there is | 97 | * Signal the completion of the last send |
147 | * one). | 98 | * (if there is one). |
148 | */ | 99 | */ |
149 | if (qp->s_last != qp->s_tail) | 100 | if (qp->s_last != qp->s_tail) |
150 | complete_last_send(qp, wqe, &wc); | 101 | complete_last_send(qp, wqe, &wc); |
@@ -257,61 +208,16 @@ again: | |||
257 | } | 208 | } |
258 | break; | 209 | break; |
259 | } | 210 | } |
260 | bth2 = qp->s_next_psn++ & IPS_PSN_MASK; | ||
261 | qp->s_len -= len; | 211 | qp->s_len -= len; |
262 | bth0 |= qp->s_state << 24; | ||
263 | |||
264 | spin_unlock_irqrestore(&qp->s_lock, flags); | ||
265 | |||
266 | /* Construct the header. */ | ||
267 | extra_bytes = (4 - len) & 3; | ||
268 | nwords = (len + extra_bytes) >> 2; | ||
269 | if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) { | ||
270 | /* Header size in 32-bit words. */ | ||
271 | hwords += 10; | ||
272 | lrh0 = IPS_LRH_GRH; | ||
273 | qp->s_hdr.u.l.grh.version_tclass_flow = | ||
274 | cpu_to_be32((6 << 28) | | ||
275 | (qp->remote_ah_attr.grh.traffic_class | ||
276 | << 20) | | ||
277 | qp->remote_ah_attr.grh.flow_label); | ||
278 | qp->s_hdr.u.l.grh.paylen = | ||
279 | cpu_to_be16(((hwords - 12) + nwords + | ||
280 | SIZE_OF_CRC) << 2); | ||
281 | /* next_hdr is defined by C8-7 in ch. 8.4.1 */ | ||
282 | qp->s_hdr.u.l.grh.next_hdr = 0x1B; | ||
283 | qp->s_hdr.u.l.grh.hop_limit = | ||
284 | qp->remote_ah_attr.grh.hop_limit; | ||
285 | /* The SGID is 32-bit aligned. */ | ||
286 | qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = | ||
287 | dev->gid_prefix; | ||
288 | qp->s_hdr.u.l.grh.sgid.global.interface_id = | ||
289 | ipath_layer_get_guid(dev->dd); | ||
290 | qp->s_hdr.u.l.grh.dgid = qp->remote_ah_attr.grh.dgid; | ||
291 | } | ||
292 | qp->s_hdrwords = hwords; | 212 | qp->s_hdrwords = hwords; |
293 | qp->s_cur_sge = &qp->s_sge; | 213 | qp->s_cur_sge = &qp->s_sge; |
294 | qp->s_cur_size = len; | 214 | qp->s_cur_size = len; |
295 | lrh0 |= qp->remote_ah_attr.sl << 4; | 215 | *bth0p = bth0 | (qp->s_state << 24); |
296 | qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); | 216 | *bth2p = qp->s_next_psn++ & IPATH_PSN_MASK; |
297 | /* DEST LID */ | 217 | return 1; |
298 | qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); | ||
299 | qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC); | ||
300 | qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); | ||
301 | bth0 |= extra_bytes << 20; | ||
302 | ohdr->bth[0] = cpu_to_be32(bth0); | ||
303 | ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); | ||
304 | ohdr->bth[2] = cpu_to_be32(bth2); | ||
305 | |||
306 | /* Check for more work to do. */ | ||
307 | goto again; | ||
308 | 218 | ||
309 | done: | 219 | done: |
310 | spin_unlock_irqrestore(&qp->s_lock, flags); | 220 | return 0; |
311 | clear_bit(IPATH_S_BUSY, &qp->s_flags); | ||
312 | |||
313 | bail: | ||
314 | return; | ||
315 | } | 221 | } |
316 | 222 | ||
317 | /** | 223 | /** |
@@ -335,7 +241,6 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
335 | u32 hdrsize; | 241 | u32 hdrsize; |
336 | u32 psn; | 242 | u32 psn; |
337 | u32 pad; | 243 | u32 pad; |
338 | unsigned long flags; | ||
339 | struct ib_wc wc; | 244 | struct ib_wc wc; |
340 | u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); | 245 | u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); |
341 | struct ib_reth *reth; | 246 | struct ib_reth *reth; |
@@ -373,8 +278,6 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
373 | wc.imm_data = 0; | 278 | wc.imm_data = 0; |
374 | wc.wc_flags = 0; | 279 | wc.wc_flags = 0; |
375 | 280 | ||
376 | spin_lock_irqsave(&qp->r_rq.lock, flags); | ||
377 | |||
378 | /* Compare the PSN verses the expected PSN. */ | 281 | /* Compare the PSN verses the expected PSN. */ |
379 | if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) { | 282 | if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) { |
380 | /* | 283 | /* |
@@ -535,12 +438,13 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
535 | if (qp->r_len != 0) { | 438 | if (qp->r_len != 0) { |
536 | u32 rkey = be32_to_cpu(reth->rkey); | 439 | u32 rkey = be32_to_cpu(reth->rkey); |
537 | u64 vaddr = be64_to_cpu(reth->vaddr); | 440 | u64 vaddr = be64_to_cpu(reth->vaddr); |
441 | int ok; | ||
538 | 442 | ||
539 | /* Check rkey */ | 443 | /* Check rkey */ |
540 | if (unlikely(!ipath_rkey_ok( | 444 | ok = ipath_rkey_ok(dev, &qp->r_sge, qp->r_len, |
541 | dev, &qp->r_sge, qp->r_len, | 445 | vaddr, rkey, |
542 | vaddr, rkey, | 446 | IB_ACCESS_REMOTE_WRITE); |
543 | IB_ACCESS_REMOTE_WRITE))) { | 447 | if (unlikely(!ok)) { |
544 | dev->n_pkt_drops++; | 448 | dev->n_pkt_drops++; |
545 | goto done; | 449 | goto done; |
546 | } | 450 | } |
@@ -558,8 +462,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
558 | } | 462 | } |
559 | if (opcode == OP(RDMA_WRITE_ONLY)) | 463 | if (opcode == OP(RDMA_WRITE_ONLY)) |
560 | goto rdma_last; | 464 | goto rdma_last; |
561 | else if (opcode == | 465 | else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) |
562 | OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) | ||
563 | goto rdma_last_imm; | 466 | goto rdma_last_imm; |
564 | /* FALLTHROUGH */ | 467 | /* FALLTHROUGH */ |
565 | case OP(RDMA_WRITE_MIDDLE): | 468 | case OP(RDMA_WRITE_MIDDLE): |
@@ -592,9 +495,9 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
592 | dev->n_pkt_drops++; | 495 | dev->n_pkt_drops++; |
593 | goto done; | 496 | goto done; |
594 | } | 497 | } |
595 | if (qp->r_reuse_sge) { | 498 | if (qp->r_reuse_sge) |
596 | qp->r_reuse_sge = 0; | 499 | qp->r_reuse_sge = 0; |
597 | } else if (!ipath_get_rwqe(qp, 1)) { | 500 | else if (!ipath_get_rwqe(qp, 1)) { |
598 | dev->n_pkt_drops++; | 501 | dev->n_pkt_drops++; |
599 | goto done; | 502 | goto done; |
600 | } | 503 | } |
@@ -631,15 +534,11 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
631 | 534 | ||
632 | default: | 535 | default: |
633 | /* Drop packet for unknown opcodes. */ | 536 | /* Drop packet for unknown opcodes. */ |
634 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
635 | dev->n_pkt_drops++; | 537 | dev->n_pkt_drops++; |
636 | goto bail; | 538 | goto done; |
637 | } | 539 | } |
638 | qp->r_psn++; | 540 | qp->r_psn++; |
639 | qp->r_state = opcode; | 541 | qp->r_state = opcode; |
640 | done: | 542 | done: |
641 | spin_unlock_irqrestore(&qp->r_rq.lock, flags); | ||
642 | |||
643 | bail: | ||
644 | return; | 543 | return; |
645 | } | 544 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index e606daf83210..3466129af804 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -33,7 +34,7 @@ | |||
33 | #include <rdma/ib_smi.h> | 34 | #include <rdma/ib_smi.h> |
34 | 35 | ||
35 | #include "ipath_verbs.h" | 36 | #include "ipath_verbs.h" |
36 | #include "ips_common.h" | 37 | #include "ipath_common.h" |
37 | 38 | ||
38 | /** | 39 | /** |
39 | * ipath_ud_loopback - handle send on loopback QPs | 40 | * ipath_ud_loopback - handle send on loopback QPs |
@@ -274,6 +275,11 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
274 | len += wr->sg_list[i].length; | 275 | len += wr->sg_list[i].length; |
275 | ss.num_sge++; | 276 | ss.num_sge++; |
276 | } | 277 | } |
278 | /* Check for invalid packet size. */ | ||
279 | if (len > ipath_layer_get_ibmtu(dev->dd)) { | ||
280 | ret = -EINVAL; | ||
281 | goto bail; | ||
282 | } | ||
277 | extra_bytes = (4 - len) & 3; | 283 | extra_bytes = (4 - len) & 3; |
278 | nwords = (len + extra_bytes) >> 2; | 284 | nwords = (len + extra_bytes) >> 2; |
279 | 285 | ||
@@ -283,8 +289,8 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
283 | ret = -EINVAL; | 289 | ret = -EINVAL; |
284 | goto bail; | 290 | goto bail; |
285 | } | 291 | } |
286 | if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE) { | 292 | if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE) { |
287 | if (ah_attr->dlid != IPS_PERMISSIVE_LID) | 293 | if (ah_attr->dlid != IPATH_PERMISSIVE_LID) |
288 | dev->n_multicast_xmit++; | 294 | dev->n_multicast_xmit++; |
289 | else | 295 | else |
290 | dev->n_unicast_xmit++; | 296 | dev->n_unicast_xmit++; |
@@ -304,7 +310,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
304 | if (ah_attr->ah_flags & IB_AH_GRH) { | 310 | if (ah_attr->ah_flags & IB_AH_GRH) { |
305 | /* Header size in 32-bit words. */ | 311 | /* Header size in 32-bit words. */ |
306 | hwords = 17; | 312 | hwords = 17; |
307 | lrh0 = IPS_LRH_GRH; | 313 | lrh0 = IPATH_LRH_GRH; |
308 | ohdr = &qp->s_hdr.u.l.oth; | 314 | ohdr = &qp->s_hdr.u.l.oth; |
309 | qp->s_hdr.u.l.grh.version_tclass_flow = | 315 | qp->s_hdr.u.l.grh.version_tclass_flow = |
310 | cpu_to_be32((6 << 28) | | 316 | cpu_to_be32((6 << 28) | |
@@ -330,7 +336,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
330 | } else { | 336 | } else { |
331 | /* Header size in 32-bit words. */ | 337 | /* Header size in 32-bit words. */ |
332 | hwords = 7; | 338 | hwords = 7; |
333 | lrh0 = IPS_LRH_BTH; | 339 | lrh0 = IPATH_LRH_BTH; |
334 | ohdr = &qp->s_hdr.u.oth; | 340 | ohdr = &qp->s_hdr.u.oth; |
335 | } | 341 | } |
336 | if (wr->opcode == IB_WR_SEND_WITH_IMM) { | 342 | if (wr->opcode == IB_WR_SEND_WITH_IMM) { |
@@ -361,18 +367,18 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) | |||
361 | if (wr->send_flags & IB_SEND_SOLICITED) | 367 | if (wr->send_flags & IB_SEND_SOLICITED) |
362 | bth0 |= 1 << 23; | 368 | bth0 |= 1 << 23; |
363 | bth0 |= extra_bytes << 20; | 369 | bth0 |= extra_bytes << 20; |
364 | bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPS_DEFAULT_P_KEY : | 370 | bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPATH_DEFAULT_P_KEY : |
365 | ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); | 371 | ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); |
366 | ohdr->bth[0] = cpu_to_be32(bth0); | 372 | ohdr->bth[0] = cpu_to_be32(bth0); |
367 | /* | 373 | /* |
368 | * Use the multicast QP if the destination LID is a multicast LID. | 374 | * Use the multicast QP if the destination LID is a multicast LID. |
369 | */ | 375 | */ |
370 | ohdr->bth[1] = ah_attr->dlid >= IPS_MULTICAST_LID_BASE && | 376 | ohdr->bth[1] = ah_attr->dlid >= IPATH_MULTICAST_LID_BASE && |
371 | ah_attr->dlid != IPS_PERMISSIVE_LID ? | 377 | ah_attr->dlid != IPATH_PERMISSIVE_LID ? |
372 | __constant_cpu_to_be32(IPS_MULTICAST_QPN) : | 378 | __constant_cpu_to_be32(IPATH_MULTICAST_QPN) : |
373 | cpu_to_be32(wr->wr.ud.remote_qpn); | 379 | cpu_to_be32(wr->wr.ud.remote_qpn); |
374 | /* XXX Could lose a PSN count but not worth locking */ | 380 | /* XXX Could lose a PSN count but not worth locking */ |
375 | ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPS_PSN_MASK); | 381 | ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPATH_PSN_MASK); |
376 | /* | 382 | /* |
377 | * Qkeys with the high order bit set mean use the | 383 | * Qkeys with the high order bit set mean use the |
378 | * qkey from the QP context instead of the WR (see 10.2.5). | 384 | * qkey from the QP context instead of the WR (see 10.2.5). |
@@ -463,7 +469,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
463 | src_qp = be32_to_cpu(ohdr->u.ud.deth[1]); | 469 | src_qp = be32_to_cpu(ohdr->u.ud.deth[1]); |
464 | } | 470 | } |
465 | } | 471 | } |
466 | src_qp &= IPS_QPN_MASK; | 472 | src_qp &= IPATH_QPN_MASK; |
467 | 473 | ||
468 | /* | 474 | /* |
469 | * Check that the permissive LID is only used on QP0 | 475 | * Check that the permissive LID is only used on QP0 |
@@ -554,7 +560,16 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
554 | spin_lock_irqsave(&rq->lock, flags); | 560 | spin_lock_irqsave(&rq->lock, flags); |
555 | if (rq->tail == rq->head) { | 561 | if (rq->tail == rq->head) { |
556 | spin_unlock_irqrestore(&rq->lock, flags); | 562 | spin_unlock_irqrestore(&rq->lock, flags); |
557 | dev->n_pkt_drops++; | 563 | /* |
564 | * Count VL15 packets dropped due to no receive buffer. | ||
565 | * Otherwise, count them as buffer overruns since usually, | ||
566 | * the HW will be able to receive packets even if there are | ||
567 | * no QPs with posted receive buffers. | ||
568 | */ | ||
569 | if (qp->ibqp.qp_num == 0) | ||
570 | dev->n_vl15_dropped++; | ||
571 | else | ||
572 | dev->rcv_errors++; | ||
558 | goto bail; | 573 | goto bail; |
559 | } | 574 | } |
560 | /* Silently drop packets which are too big. */ | 575 | /* Silently drop packets which are too big. */ |
@@ -612,7 +627,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
612 | /* | 627 | /* |
613 | * Save the LMC lower bits if the destination LID is a unicast LID. | 628 | * Save the LMC lower bits if the destination LID is a unicast LID. |
614 | */ | 629 | */ |
615 | wc.dlid_path_bits = dlid >= IPS_MULTICAST_LID_BASE ? 0 : | 630 | wc.dlid_path_bits = dlid >= IPATH_MULTICAST_LID_BASE ? 0 : |
616 | dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); | 631 | dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); |
617 | /* Signal completion event if the solicited bit is set. */ | 632 | /* Signal completion event if the solicited bit is set. */ |
618 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, | 633 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, |
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c index 2bb08afc86d0..e32fca9faf80 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_pages.c +++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -57,17 +58,6 @@ static int __get_user_pages(unsigned long start_page, size_t num_pages, | |||
57 | size_t got; | 58 | size_t got; |
58 | int ret; | 59 | int ret; |
59 | 60 | ||
60 | #if 0 | ||
61 | /* | ||
62 | * XXX - causes MPI programs to fail, haven't had time to check | ||
63 | * yet | ||
64 | */ | ||
65 | if (!capable(CAP_IPC_LOCK)) { | ||
66 | ret = -EPERM; | ||
67 | goto bail; | ||
68 | } | ||
69 | #endif | ||
70 | |||
71 | lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> | 61 | lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> |
72 | PAGE_SHIFT; | 62 | PAGE_SHIFT; |
73 | 63 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 28fdbdaa789d..56ac336dd1ec 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -36,7 +37,7 @@ | |||
36 | 37 | ||
37 | #include "ipath_kernel.h" | 38 | #include "ipath_kernel.h" |
38 | #include "ipath_verbs.h" | 39 | #include "ipath_verbs.h" |
39 | #include "ips_common.h" | 40 | #include "ipath_common.h" |
40 | 41 | ||
41 | /* Not static, because we don't want the compiler removing it */ | 42 | /* Not static, because we don't want the compiler removing it */ |
42 | const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR; | 43 | const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR; |
@@ -55,9 +56,62 @@ unsigned int ib_ipath_debug; /* debug mask */ | |||
55 | module_param_named(debug, ib_ipath_debug, uint, S_IWUSR | S_IRUGO); | 56 | module_param_named(debug, ib_ipath_debug, uint, S_IWUSR | S_IRUGO); |
56 | MODULE_PARM_DESC(debug, "Verbs debug mask"); | 57 | MODULE_PARM_DESC(debug, "Verbs debug mask"); |
57 | 58 | ||
59 | static unsigned int ib_ipath_max_pds = 0xFFFF; | ||
60 | module_param_named(max_pds, ib_ipath_max_pds, uint, S_IWUSR | S_IRUGO); | ||
61 | MODULE_PARM_DESC(max_pds, | ||
62 | "Maximum number of protection domains to support"); | ||
63 | |||
64 | static unsigned int ib_ipath_max_ahs = 0xFFFF; | ||
65 | module_param_named(max_ahs, ib_ipath_max_ahs, uint, S_IWUSR | S_IRUGO); | ||
66 | MODULE_PARM_DESC(max_ahs, "Maximum number of address handles to support"); | ||
67 | |||
68 | unsigned int ib_ipath_max_cqes = 0x2FFFF; | ||
69 | module_param_named(max_cqes, ib_ipath_max_cqes, uint, S_IWUSR | S_IRUGO); | ||
70 | MODULE_PARM_DESC(max_cqes, | ||
71 | "Maximum number of completion queue entries to support"); | ||
72 | |||
73 | unsigned int ib_ipath_max_cqs = 0x1FFFF; | ||
74 | module_param_named(max_cqs, ib_ipath_max_cqs, uint, S_IWUSR | S_IRUGO); | ||
75 | MODULE_PARM_DESC(max_cqs, "Maximum number of completion queues to support"); | ||
76 | |||
77 | unsigned int ib_ipath_max_qp_wrs = 0x3FFF; | ||
78 | module_param_named(max_qp_wrs, ib_ipath_max_qp_wrs, uint, | ||
79 | S_IWUSR | S_IRUGO); | ||
80 | MODULE_PARM_DESC(max_qp_wrs, "Maximum number of QP WRs to support"); | ||
81 | |||
82 | unsigned int ib_ipath_max_sges = 0x60; | ||
83 | module_param_named(max_sges, ib_ipath_max_sges, uint, S_IWUSR | S_IRUGO); | ||
84 | MODULE_PARM_DESC(max_sges, "Maximum number of SGEs to support"); | ||
85 | |||
86 | unsigned int ib_ipath_max_mcast_grps = 16384; | ||
87 | module_param_named(max_mcast_grps, ib_ipath_max_mcast_grps, uint, | ||
88 | S_IWUSR | S_IRUGO); | ||
89 | MODULE_PARM_DESC(max_mcast_grps, | ||
90 | "Maximum number of multicast groups to support"); | ||
91 | |||
92 | unsigned int ib_ipath_max_mcast_qp_attached = 16; | ||
93 | module_param_named(max_mcast_qp_attached, ib_ipath_max_mcast_qp_attached, | ||
94 | uint, S_IWUSR | S_IRUGO); | ||
95 | MODULE_PARM_DESC(max_mcast_qp_attached, | ||
96 | "Maximum number of attached QPs to support"); | ||
97 | |||
98 | unsigned int ib_ipath_max_srqs = 1024; | ||
99 | module_param_named(max_srqs, ib_ipath_max_srqs, uint, S_IWUSR | S_IRUGO); | ||
100 | MODULE_PARM_DESC(max_srqs, "Maximum number of SRQs to support"); | ||
101 | |||
102 | unsigned int ib_ipath_max_srq_sges = 128; | ||
103 | module_param_named(max_srq_sges, ib_ipath_max_srq_sges, | ||
104 | uint, S_IWUSR | S_IRUGO); | ||
105 | MODULE_PARM_DESC(max_srq_sges, "Maximum number of SRQ SGEs to support"); | ||
106 | |||
107 | unsigned int ib_ipath_max_srq_wrs = 0x1FFFF; | ||
108 | module_param_named(max_srq_wrs, ib_ipath_max_srq_wrs, | ||
109 | uint, S_IWUSR | S_IRUGO); | ||
110 | MODULE_PARM_DESC(max_srq_wrs, "Maximum number of SRQ WRs support"); | ||
111 | |||
58 | MODULE_LICENSE("GPL"); | 112 | MODULE_LICENSE("GPL"); |
59 | MODULE_AUTHOR("PathScale <support@pathscale.com>"); | 113 | MODULE_AUTHOR("QLogic <support@pathscale.com>"); |
60 | MODULE_DESCRIPTION("Pathscale InfiniPath driver"); | 114 | MODULE_DESCRIPTION("QLogic InfiniPath driver"); |
61 | 115 | ||
62 | const int ib_ipath_state_ops[IB_QPS_ERR + 1] = { | 116 | const int ib_ipath_state_ops[IB_QPS_ERR + 1] = { |
63 | [IB_QPS_RESET] = 0, | 117 | [IB_QPS_RESET] = 0, |
@@ -193,7 +247,7 @@ static int ipath_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
193 | switch (qp->ibqp.qp_type) { | 247 | switch (qp->ibqp.qp_type) { |
194 | case IB_QPT_UC: | 248 | case IB_QPT_UC: |
195 | case IB_QPT_RC: | 249 | case IB_QPT_RC: |
196 | err = ipath_post_rc_send(qp, wr); | 250 | err = ipath_post_ruc_send(qp, wr); |
197 | break; | 251 | break; |
198 | 252 | ||
199 | case IB_QPT_SMI: | 253 | case IB_QPT_SMI: |
@@ -375,7 +429,7 @@ static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen) | |||
375 | 429 | ||
376 | /* Check for a valid destination LID (see ch. 7.11.1). */ | 430 | /* Check for a valid destination LID (see ch. 7.11.1). */ |
377 | lid = be16_to_cpu(hdr->lrh[1]); | 431 | lid = be16_to_cpu(hdr->lrh[1]); |
378 | if (lid < IPS_MULTICAST_LID_BASE) { | 432 | if (lid < IPATH_MULTICAST_LID_BASE) { |
379 | lid &= ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); | 433 | lid &= ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); |
380 | if (unlikely(lid != ipath_layer_get_lid(dev->dd))) { | 434 | if (unlikely(lid != ipath_layer_get_lid(dev->dd))) { |
381 | dev->rcv_errors++; | 435 | dev->rcv_errors++; |
@@ -385,9 +439,9 @@ static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen) | |||
385 | 439 | ||
386 | /* Check for GRH */ | 440 | /* Check for GRH */ |
387 | lnh = be16_to_cpu(hdr->lrh[0]) & 3; | 441 | lnh = be16_to_cpu(hdr->lrh[0]) & 3; |
388 | if (lnh == IPS_LRH_BTH) | 442 | if (lnh == IPATH_LRH_BTH) |
389 | ohdr = &hdr->u.oth; | 443 | ohdr = &hdr->u.oth; |
390 | else if (lnh == IPS_LRH_GRH) | 444 | else if (lnh == IPATH_LRH_GRH) |
391 | ohdr = &hdr->u.l.oth; | 445 | ohdr = &hdr->u.l.oth; |
392 | else { | 446 | else { |
393 | dev->rcv_errors++; | 447 | dev->rcv_errors++; |
@@ -399,8 +453,8 @@ static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen) | |||
399 | dev->opstats[opcode].n_packets++; | 453 | dev->opstats[opcode].n_packets++; |
400 | 454 | ||
401 | /* Get the destination QP number. */ | 455 | /* Get the destination QP number. */ |
402 | qp_num = be32_to_cpu(ohdr->bth[1]) & IPS_QPN_MASK; | 456 | qp_num = be32_to_cpu(ohdr->bth[1]) & IPATH_QPN_MASK; |
403 | if (qp_num == IPS_MULTICAST_QPN) { | 457 | if (qp_num == IPATH_MULTICAST_QPN) { |
404 | struct ipath_mcast *mcast; | 458 | struct ipath_mcast *mcast; |
405 | struct ipath_mcast_qp *p; | 459 | struct ipath_mcast_qp *p; |
406 | 460 | ||
@@ -411,7 +465,7 @@ static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen) | |||
411 | } | 465 | } |
412 | dev->n_multicast_rcv++; | 466 | dev->n_multicast_rcv++; |
413 | list_for_each_entry_rcu(p, &mcast->qp_list, list) | 467 | list_for_each_entry_rcu(p, &mcast->qp_list, list) |
414 | ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data, | 468 | ipath_qp_rcv(dev, hdr, lnh == IPATH_LRH_GRH, data, |
415 | tlen, p->qp); | 469 | tlen, p->qp); |
416 | /* | 470 | /* |
417 | * Notify ipath_multicast_detach() if it is waiting for us | 471 | * Notify ipath_multicast_detach() if it is waiting for us |
@@ -423,7 +477,7 @@ static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen) | |||
423 | qp = ipath_lookup_qpn(&dev->qp_table, qp_num); | 477 | qp = ipath_lookup_qpn(&dev->qp_table, qp_num); |
424 | if (qp) { | 478 | if (qp) { |
425 | dev->n_unicast_rcv++; | 479 | dev->n_unicast_rcv++; |
426 | ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data, | 480 | ipath_qp_rcv(dev, hdr, lnh == IPATH_LRH_GRH, data, |
427 | tlen, qp); | 481 | tlen, qp); |
428 | /* | 482 | /* |
429 | * Notify ipath_destroy_qp() if it is waiting | 483 | * Notify ipath_destroy_qp() if it is waiting |
@@ -567,40 +621,38 @@ static int ipath_query_device(struct ib_device *ibdev, | |||
567 | struct ib_device_attr *props) | 621 | struct ib_device_attr *props) |
568 | { | 622 | { |
569 | struct ipath_ibdev *dev = to_idev(ibdev); | 623 | struct ipath_ibdev *dev = to_idev(ibdev); |
570 | u32 vendor, boardrev, majrev, minrev; | ||
571 | 624 | ||
572 | memset(props, 0, sizeof(*props)); | 625 | memset(props, 0, sizeof(*props)); |
573 | 626 | ||
574 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | | 627 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | |
575 | IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | | 628 | IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | |
576 | IB_DEVICE_SYS_IMAGE_GUID; | 629 | IB_DEVICE_SYS_IMAGE_GUID; |
577 | ipath_layer_query_device(dev->dd, &vendor, &boardrev, | 630 | props->vendor_id = ipath_layer_get_vendorid(dev->dd); |
578 | &majrev, &minrev); | 631 | props->vendor_part_id = ipath_layer_get_deviceid(dev->dd); |
579 | props->vendor_id = vendor; | 632 | props->hw_ver = ipath_layer_get_pcirev(dev->dd); |
580 | props->vendor_part_id = boardrev; | ||
581 | props->hw_ver = boardrev << 16 | majrev << 8 | minrev; | ||
582 | 633 | ||
583 | props->sys_image_guid = dev->sys_image_guid; | 634 | props->sys_image_guid = dev->sys_image_guid; |
584 | 635 | ||
585 | props->max_mr_size = ~0ull; | 636 | props->max_mr_size = ~0ull; |
586 | props->max_qp = 0xffff; | 637 | props->max_qp = dev->qp_table.max; |
587 | props->max_qp_wr = 0xffff; | 638 | props->max_qp_wr = ib_ipath_max_qp_wrs; |
588 | props->max_sge = 255; | 639 | props->max_sge = ib_ipath_max_sges; |
589 | props->max_cq = 0xffff; | 640 | props->max_cq = ib_ipath_max_cqs; |
590 | props->max_cqe = 0xffff; | 641 | props->max_ah = ib_ipath_max_ahs; |
591 | props->max_mr = 0xffff; | 642 | props->max_cqe = ib_ipath_max_cqes; |
592 | props->max_pd = 0xffff; | 643 | props->max_mr = dev->lk_table.max; |
644 | props->max_pd = ib_ipath_max_pds; | ||
593 | props->max_qp_rd_atom = 1; | 645 | props->max_qp_rd_atom = 1; |
594 | props->max_qp_init_rd_atom = 1; | 646 | props->max_qp_init_rd_atom = 1; |
595 | /* props->max_res_rd_atom */ | 647 | /* props->max_res_rd_atom */ |
596 | props->max_srq = 0xffff; | 648 | props->max_srq = ib_ipath_max_srqs; |
597 | props->max_srq_wr = 0xffff; | 649 | props->max_srq_wr = ib_ipath_max_srq_wrs; |
598 | props->max_srq_sge = 255; | 650 | props->max_srq_sge = ib_ipath_max_srq_sges; |
599 | /* props->local_ca_ack_delay */ | 651 | /* props->local_ca_ack_delay */ |
600 | props->atomic_cap = IB_ATOMIC_HCA; | 652 | props->atomic_cap = IB_ATOMIC_HCA; |
601 | props->max_pkeys = ipath_layer_get_npkeys(dev->dd); | 653 | props->max_pkeys = ipath_layer_get_npkeys(dev->dd); |
602 | props->max_mcast_grp = 0xffff; | 654 | props->max_mcast_grp = ib_ipath_max_mcast_grps; |
603 | props->max_mcast_qp_attach = 0xffff; | 655 | props->max_mcast_qp_attach = ib_ipath_max_mcast_qp_attached; |
604 | props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * | 656 | props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * |
605 | props->max_mcast_grp; | 657 | props->max_mcast_grp; |
606 | 658 | ||
@@ -643,10 +695,10 @@ static int ipath_query_port(struct ib_device *ibdev, | |||
643 | ipath_layer_get_lastibcstat(dev->dd) & 0xf]; | 695 | ipath_layer_get_lastibcstat(dev->dd) & 0xf]; |
644 | props->port_cap_flags = dev->port_cap_flags; | 696 | props->port_cap_flags = dev->port_cap_flags; |
645 | props->gid_tbl_len = 1; | 697 | props->gid_tbl_len = 1; |
646 | props->max_msg_sz = 4096; | 698 | props->max_msg_sz = 0x80000000; |
647 | props->pkey_tbl_len = ipath_layer_get_npkeys(dev->dd); | 699 | props->pkey_tbl_len = ipath_layer_get_npkeys(dev->dd); |
648 | props->bad_pkey_cntr = ipath_layer_get_cr_errpkey(dev->dd) - | 700 | props->bad_pkey_cntr = ipath_layer_get_cr_errpkey(dev->dd) - |
649 | dev->n_pkey_violations; | 701 | dev->z_pkey_violations; |
650 | props->qkey_viol_cntr = dev->qkey_violations; | 702 | props->qkey_viol_cntr = dev->qkey_violations; |
651 | props->active_width = IB_WIDTH_4X; | 703 | props->active_width = IB_WIDTH_4X; |
652 | /* See rate_show() */ | 704 | /* See rate_show() */ |
@@ -743,15 +795,30 @@ static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev, | |||
743 | struct ib_ucontext *context, | 795 | struct ib_ucontext *context, |
744 | struct ib_udata *udata) | 796 | struct ib_udata *udata) |
745 | { | 797 | { |
798 | struct ipath_ibdev *dev = to_idev(ibdev); | ||
746 | struct ipath_pd *pd; | 799 | struct ipath_pd *pd; |
747 | struct ib_pd *ret; | 800 | struct ib_pd *ret; |
748 | 801 | ||
802 | /* | ||
803 | * This is actually totally arbitrary. Some correctness tests | ||
804 | * assume there's a maximum number of PDs that can be allocated. | ||
805 | * We don't actually have this limit, but we fail the test if | ||
806 | * we allow allocations of more than we report for this value. | ||
807 | */ | ||
808 | |||
809 | if (dev->n_pds_allocated == ib_ipath_max_pds) { | ||
810 | ret = ERR_PTR(-ENOMEM); | ||
811 | goto bail; | ||
812 | } | ||
813 | |||
749 | pd = kmalloc(sizeof *pd, GFP_KERNEL); | 814 | pd = kmalloc(sizeof *pd, GFP_KERNEL); |
750 | if (!pd) { | 815 | if (!pd) { |
751 | ret = ERR_PTR(-ENOMEM); | 816 | ret = ERR_PTR(-ENOMEM); |
752 | goto bail; | 817 | goto bail; |
753 | } | 818 | } |
754 | 819 | ||
820 | dev->n_pds_allocated++; | ||
821 | |||
755 | /* ib_alloc_pd() will initialize pd->ibpd. */ | 822 | /* ib_alloc_pd() will initialize pd->ibpd. */ |
756 | pd->user = udata != NULL; | 823 | pd->user = udata != NULL; |
757 | 824 | ||
@@ -764,6 +831,9 @@ bail: | |||
764 | static int ipath_dealloc_pd(struct ib_pd *ibpd) | 831 | static int ipath_dealloc_pd(struct ib_pd *ibpd) |
765 | { | 832 | { |
766 | struct ipath_pd *pd = to_ipd(ibpd); | 833 | struct ipath_pd *pd = to_ipd(ibpd); |
834 | struct ipath_ibdev *dev = to_idev(ibpd->device); | ||
835 | |||
836 | dev->n_pds_allocated--; | ||
767 | 837 | ||
768 | kfree(pd); | 838 | kfree(pd); |
769 | 839 | ||
@@ -782,21 +852,40 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd, | |||
782 | { | 852 | { |
783 | struct ipath_ah *ah; | 853 | struct ipath_ah *ah; |
784 | struct ib_ah *ret; | 854 | struct ib_ah *ret; |
855 | struct ipath_ibdev *dev = to_idev(pd->device); | ||
856 | |||
857 | if (dev->n_ahs_allocated == ib_ipath_max_ahs) { | ||
858 | ret = ERR_PTR(-ENOMEM); | ||
859 | goto bail; | ||
860 | } | ||
785 | 861 | ||
786 | /* A multicast address requires a GRH (see ch. 8.4.1). */ | 862 | /* A multicast address requires a GRH (see ch. 8.4.1). */ |
787 | if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE && | 863 | if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE && |
788 | ah_attr->dlid != IPS_PERMISSIVE_LID && | 864 | ah_attr->dlid != IPATH_PERMISSIVE_LID && |
789 | !(ah_attr->ah_flags & IB_AH_GRH)) { | 865 | !(ah_attr->ah_flags & IB_AH_GRH)) { |
790 | ret = ERR_PTR(-EINVAL); | 866 | ret = ERR_PTR(-EINVAL); |
791 | goto bail; | 867 | goto bail; |
792 | } | 868 | } |
793 | 869 | ||
870 | if (ah_attr->dlid == 0) { | ||
871 | ret = ERR_PTR(-EINVAL); | ||
872 | goto bail; | ||
873 | } | ||
874 | |||
875 | if (ah_attr->port_num < 1 || | ||
876 | ah_attr->port_num > pd->device->phys_port_cnt) { | ||
877 | ret = ERR_PTR(-EINVAL); | ||
878 | goto bail; | ||
879 | } | ||
880 | |||
794 | ah = kmalloc(sizeof *ah, GFP_ATOMIC); | 881 | ah = kmalloc(sizeof *ah, GFP_ATOMIC); |
795 | if (!ah) { | 882 | if (!ah) { |
796 | ret = ERR_PTR(-ENOMEM); | 883 | ret = ERR_PTR(-ENOMEM); |
797 | goto bail; | 884 | goto bail; |
798 | } | 885 | } |
799 | 886 | ||
887 | dev->n_ahs_allocated++; | ||
888 | |||
800 | /* ib_create_ah() will initialize ah->ibah. */ | 889 | /* ib_create_ah() will initialize ah->ibah. */ |
801 | ah->attr = *ah_attr; | 890 | ah->attr = *ah_attr; |
802 | 891 | ||
@@ -814,8 +903,11 @@ bail: | |||
814 | */ | 903 | */ |
815 | static int ipath_destroy_ah(struct ib_ah *ibah) | 904 | static int ipath_destroy_ah(struct ib_ah *ibah) |
816 | { | 905 | { |
906 | struct ipath_ibdev *dev = to_idev(ibah->device); | ||
817 | struct ipath_ah *ah = to_iah(ibah); | 907 | struct ipath_ah *ah = to_iah(ibah); |
818 | 908 | ||
909 | dev->n_ahs_allocated--; | ||
910 | |||
819 | kfree(ah); | 911 | kfree(ah); |
820 | 912 | ||
821 | return 0; | 913 | return 0; |
@@ -889,6 +981,7 @@ static int ipath_verbs_register_sysfs(struct ib_device *dev); | |||
889 | */ | 981 | */ |
890 | static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd) | 982 | static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd) |
891 | { | 983 | { |
984 | struct ipath_layer_counters cntrs; | ||
892 | struct ipath_ibdev *idev; | 985 | struct ipath_ibdev *idev; |
893 | struct ib_device *dev; | 986 | struct ib_device *dev; |
894 | int ret; | 987 | int ret; |
@@ -939,6 +1032,25 @@ static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd) | |||
939 | idev->pma_counter_select[5] = IB_PMA_PORT_XMIT_WAIT; | 1032 | idev->pma_counter_select[5] = IB_PMA_PORT_XMIT_WAIT; |
940 | idev->link_width_enabled = 3; /* 1x or 4x */ | 1033 | idev->link_width_enabled = 3; /* 1x or 4x */ |
941 | 1034 | ||
1035 | /* Snapshot current HW counters to "clear" them. */ | ||
1036 | ipath_layer_get_counters(dd, &cntrs); | ||
1037 | idev->z_symbol_error_counter = cntrs.symbol_error_counter; | ||
1038 | idev->z_link_error_recovery_counter = | ||
1039 | cntrs.link_error_recovery_counter; | ||
1040 | idev->z_link_downed_counter = cntrs.link_downed_counter; | ||
1041 | idev->z_port_rcv_errors = cntrs.port_rcv_errors; | ||
1042 | idev->z_port_rcv_remphys_errors = | ||
1043 | cntrs.port_rcv_remphys_errors; | ||
1044 | idev->z_port_xmit_discards = cntrs.port_xmit_discards; | ||
1045 | idev->z_port_xmit_data = cntrs.port_xmit_data; | ||
1046 | idev->z_port_rcv_data = cntrs.port_rcv_data; | ||
1047 | idev->z_port_xmit_packets = cntrs.port_xmit_packets; | ||
1048 | idev->z_port_rcv_packets = cntrs.port_rcv_packets; | ||
1049 | idev->z_local_link_integrity_errors = | ||
1050 | cntrs.local_link_integrity_errors; | ||
1051 | idev->z_excessive_buffer_overrun_errors = | ||
1052 | cntrs.excessive_buffer_overrun_errors; | ||
1053 | |||
942 | /* | 1054 | /* |
943 | * The system image GUID is supposed to be the same for all | 1055 | * The system image GUID is supposed to be the same for all |
944 | * IB HCAs in a single system but since there can be other | 1056 | * IB HCAs in a single system but since there can be other |
@@ -1109,11 +1221,8 @@ static ssize_t show_rev(struct class_device *cdev, char *buf) | |||
1109 | { | 1221 | { |
1110 | struct ipath_ibdev *dev = | 1222 | struct ipath_ibdev *dev = |
1111 | container_of(cdev, struct ipath_ibdev, ibdev.class_dev); | 1223 | container_of(cdev, struct ipath_ibdev, ibdev.class_dev); |
1112 | int vendor, boardrev, majrev, minrev; | ||
1113 | 1224 | ||
1114 | ipath_layer_query_device(dev->dd, &vendor, &boardrev, | 1225 | return sprintf(buf, "%x\n", ipath_layer_get_pcirev(dev->dd)); |
1115 | &majrev, &minrev); | ||
1116 | return sprintf(buf, "%d.%d\n", majrev, minrev); | ||
1117 | } | 1226 | } |
1118 | 1227 | ||
1119 | static ssize_t show_hca(struct class_device *cdev, char *buf) | 1228 | static ssize_t show_hca(struct class_device *cdev, char *buf) |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index 4f8d59300e9b..2df684727dc1 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -148,6 +149,7 @@ struct ipath_mcast { | |||
148 | struct list_head qp_list; | 149 | struct list_head qp_list; |
149 | wait_queue_head_t wait; | 150 | wait_queue_head_t wait; |
150 | atomic_t refcount; | 151 | atomic_t refcount; |
152 | int n_attached; | ||
151 | }; | 153 | }; |
152 | 154 | ||
153 | /* Memory region */ | 155 | /* Memory region */ |
@@ -305,32 +307,34 @@ struct ipath_qp { | |||
305 | u32 s_next_psn; /* PSN for next request */ | 307 | u32 s_next_psn; /* PSN for next request */ |
306 | u32 s_last_psn; /* last response PSN processed */ | 308 | u32 s_last_psn; /* last response PSN processed */ |
307 | u32 s_psn; /* current packet sequence number */ | 309 | u32 s_psn; /* current packet sequence number */ |
310 | u32 s_ack_psn; /* PSN for RDMA_READ */ | ||
308 | u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */ | 311 | u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */ |
309 | u32 s_ack_psn; /* PSN for next ACK or RDMA_READ */ | 312 | u32 r_ack_psn; /* PSN for next ACK or atomic ACK */ |
310 | u64 s_ack_atomic; /* data for atomic ACK */ | ||
311 | u64 r_wr_id; /* ID for current receive WQE */ | 313 | u64 r_wr_id; /* ID for current receive WQE */ |
312 | u64 r_atomic_data; /* data for last atomic op */ | 314 | u64 r_atomic_data; /* data for last atomic op */ |
313 | u32 r_atomic_psn; /* PSN of last atomic op */ | 315 | u32 r_atomic_psn; /* PSN of last atomic op */ |
314 | u32 r_len; /* total length of r_sge */ | 316 | u32 r_len; /* total length of r_sge */ |
315 | u32 r_rcv_len; /* receive data len processed */ | 317 | u32 r_rcv_len; /* receive data len processed */ |
316 | u32 r_psn; /* expected rcv packet sequence number */ | 318 | u32 r_psn; /* expected rcv packet sequence number */ |
319 | u32 r_msn; /* message sequence number */ | ||
317 | u8 state; /* QP state */ | 320 | u8 state; /* QP state */ |
318 | u8 s_state; /* opcode of last packet sent */ | 321 | u8 s_state; /* opcode of last packet sent */ |
319 | u8 s_ack_state; /* opcode of packet to ACK */ | 322 | u8 s_ack_state; /* opcode of packet to ACK */ |
320 | u8 s_nak_state; /* non-zero if NAK is pending */ | 323 | u8 s_nak_state; /* non-zero if NAK is pending */ |
321 | u8 r_state; /* opcode of last packet received */ | 324 | u8 r_state; /* opcode of last packet received */ |
325 | u8 r_ack_state; /* opcode of packet to ACK */ | ||
326 | u8 r_nak_state; /* non-zero if NAK is pending */ | ||
327 | u8 r_min_rnr_timer; /* retry timeout value for RNR NAKs */ | ||
322 | u8 r_reuse_sge; /* for UC receive errors */ | 328 | u8 r_reuse_sge; /* for UC receive errors */ |
323 | u8 r_sge_inx; /* current index into sg_list */ | 329 | u8 r_sge_inx; /* current index into sg_list */ |
324 | u8 s_max_sge; /* size of s_wq->sg_list */ | ||
325 | u8 qp_access_flags; | 330 | u8 qp_access_flags; |
331 | u8 s_max_sge; /* size of s_wq->sg_list */ | ||
326 | u8 s_retry_cnt; /* number of times to retry */ | 332 | u8 s_retry_cnt; /* number of times to retry */ |
327 | u8 s_rnr_retry_cnt; | 333 | u8 s_rnr_retry_cnt; |
328 | u8 s_min_rnr_timer; | ||
329 | u8 s_retry; /* requester retry counter */ | 334 | u8 s_retry; /* requester retry counter */ |
330 | u8 s_rnr_retry; /* requester RNR retry counter */ | 335 | u8 s_rnr_retry; /* requester RNR retry counter */ |
331 | u8 s_pkey_index; /* PKEY index to use */ | 336 | u8 s_pkey_index; /* PKEY index to use */ |
332 | enum ib_mtu path_mtu; | 337 | enum ib_mtu path_mtu; |
333 | atomic_t msn; /* message sequence number */ | ||
334 | u32 remote_qpn; | 338 | u32 remote_qpn; |
335 | u32 qkey; /* QKEY for this QP (for UD or RD) */ | 339 | u32 qkey; /* QKEY for this QP (for UD or RD) */ |
336 | u32 s_size; /* send work queue size */ | 340 | u32 s_size; /* send work queue size */ |
@@ -431,6 +435,11 @@ struct ipath_ibdev { | |||
431 | __be64 sys_image_guid; /* in network order */ | 435 | __be64 sys_image_guid; /* in network order */ |
432 | __be64 gid_prefix; /* in network order */ | 436 | __be64 gid_prefix; /* in network order */ |
433 | __be64 mkey; | 437 | __be64 mkey; |
438 | u32 n_pds_allocated; /* number of PDs allocated for device */ | ||
439 | u32 n_ahs_allocated; /* number of AHs allocated for device */ | ||
440 | u32 n_cqs_allocated; /* number of CQs allocated for device */ | ||
441 | u32 n_srqs_allocated; /* number of SRQs allocated for device */ | ||
442 | u32 n_mcast_grps_allocated; /* number of mcast groups allocated */ | ||
434 | u64 ipath_sword; /* total dwords sent (sample result) */ | 443 | u64 ipath_sword; /* total dwords sent (sample result) */ |
435 | u64 ipath_rword; /* total dwords received (sample result) */ | 444 | u64 ipath_rword; /* total dwords received (sample result) */ |
436 | u64 ipath_spkts; /* total packets sent (sample result) */ | 445 | u64 ipath_spkts; /* total packets sent (sample result) */ |
@@ -442,17 +451,19 @@ struct ipath_ibdev { | |||
442 | u64 n_unicast_rcv; /* total unicast packets received */ | 451 | u64 n_unicast_rcv; /* total unicast packets received */ |
443 | u64 n_multicast_xmit; /* total multicast packets sent */ | 452 | u64 n_multicast_xmit; /* total multicast packets sent */ |
444 | u64 n_multicast_rcv; /* total multicast packets received */ | 453 | u64 n_multicast_rcv; /* total multicast packets received */ |
445 | u64 n_symbol_error_counter; /* starting count for PMA */ | 454 | u64 z_symbol_error_counter; /* starting count for PMA */ |
446 | u64 n_link_error_recovery_counter; /* starting count for PMA */ | 455 | u64 z_link_error_recovery_counter; /* starting count for PMA */ |
447 | u64 n_link_downed_counter; /* starting count for PMA */ | 456 | u64 z_link_downed_counter; /* starting count for PMA */ |
448 | u64 n_port_rcv_errors; /* starting count for PMA */ | 457 | u64 z_port_rcv_errors; /* starting count for PMA */ |
449 | u64 n_port_rcv_remphys_errors; /* starting count for PMA */ | 458 | u64 z_port_rcv_remphys_errors; /* starting count for PMA */ |
450 | u64 n_port_xmit_discards; /* starting count for PMA */ | 459 | u64 z_port_xmit_discards; /* starting count for PMA */ |
451 | u64 n_port_xmit_data; /* starting count for PMA */ | 460 | u64 z_port_xmit_data; /* starting count for PMA */ |
452 | u64 n_port_rcv_data; /* starting count for PMA */ | 461 | u64 z_port_rcv_data; /* starting count for PMA */ |
453 | u64 n_port_xmit_packets; /* starting count for PMA */ | 462 | u64 z_port_xmit_packets; /* starting count for PMA */ |
454 | u64 n_port_rcv_packets; /* starting count for PMA */ | 463 | u64 z_port_rcv_packets; /* starting count for PMA */ |
455 | u32 n_pkey_violations; /* starting count for PMA */ | 464 | u32 z_pkey_violations; /* starting count for PMA */ |
465 | u32 z_local_link_integrity_errors; /* starting count for PMA */ | ||
466 | u32 z_excessive_buffer_overrun_errors; /* starting count for PMA */ | ||
456 | u32 n_rc_resends; | 467 | u32 n_rc_resends; |
457 | u32 n_rc_acks; | 468 | u32 n_rc_acks; |
458 | u32 n_rc_qacks; | 469 | u32 n_rc_qacks; |
@@ -462,6 +473,7 @@ struct ipath_ibdev { | |||
462 | u32 n_other_naks; | 473 | u32 n_other_naks; |
463 | u32 n_timeouts; | 474 | u32 n_timeouts; |
464 | u32 n_pkt_drops; | 475 | u32 n_pkt_drops; |
476 | u32 n_vl15_dropped; | ||
465 | u32 n_wqe_errs; | 477 | u32 n_wqe_errs; |
466 | u32 n_rdma_dup_busy; | 478 | u32 n_rdma_dup_busy; |
467 | u32 n_piowait; | 479 | u32 n_piowait; |
@@ -580,10 +592,6 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc); | |||
580 | 592 | ||
581 | void ipath_get_credit(struct ipath_qp *qp, u32 aeth); | 593 | void ipath_get_credit(struct ipath_qp *qp, u32 aeth); |
582 | 594 | ||
583 | void ipath_do_rc_send(unsigned long data); | ||
584 | |||
585 | void ipath_do_uc_send(unsigned long data); | ||
586 | |||
587 | void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig); | 595 | void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig); |
588 | 596 | ||
589 | int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, | 597 | int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, |
@@ -596,7 +604,7 @@ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length); | |||
596 | 604 | ||
597 | void ipath_skip_sge(struct ipath_sge_state *ss, u32 length); | 605 | void ipath_skip_sge(struct ipath_sge_state *ss, u32 length); |
598 | 606 | ||
599 | int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr); | 607 | int ipath_post_ruc_send(struct ipath_qp *qp, struct ib_send_wr *wr); |
600 | 608 | ||
601 | void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | 609 | void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, |
602 | int has_grh, void *data, u32 tlen, struct ipath_qp *qp); | 610 | int has_grh, void *data, u32 tlen, struct ipath_qp *qp); |
@@ -678,7 +686,19 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp); | |||
678 | 686 | ||
679 | int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only); | 687 | int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only); |
680 | 688 | ||
681 | void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc); | 689 | u32 ipath_make_grh(struct ipath_ibdev *dev, struct ib_grh *hdr, |
690 | struct ib_global_route *grh, u32 hwords, u32 nwords); | ||
691 | |||
692 | void ipath_do_ruc_send(unsigned long data); | ||
693 | |||
694 | u32 ipath_make_rc_ack(struct ipath_qp *qp, struct ipath_other_headers *ohdr, | ||
695 | u32 pmtu); | ||
696 | |||
697 | int ipath_make_rc_req(struct ipath_qp *qp, struct ipath_other_headers *ohdr, | ||
698 | u32 pmtu, u32 *bth0p, u32 *bth2p); | ||
699 | |||
700 | int ipath_make_uc_req(struct ipath_qp *qp, struct ipath_other_headers *ohdr, | ||
701 | u32 pmtu, u32 *bth0p, u32 *bth2p); | ||
682 | 702 | ||
683 | extern const enum ib_wc_opcode ib_ipath_wc_opcode[]; | 703 | extern const enum ib_wc_opcode ib_ipath_wc_opcode[]; |
684 | 704 | ||
@@ -688,6 +708,24 @@ extern const int ib_ipath_state_ops[]; | |||
688 | 708 | ||
689 | extern unsigned int ib_ipath_lkey_table_size; | 709 | extern unsigned int ib_ipath_lkey_table_size; |
690 | 710 | ||
711 | extern unsigned int ib_ipath_max_cqes; | ||
712 | |||
713 | extern unsigned int ib_ipath_max_cqs; | ||
714 | |||
715 | extern unsigned int ib_ipath_max_qp_wrs; | ||
716 | |||
717 | extern unsigned int ib_ipath_max_sges; | ||
718 | |||
719 | extern unsigned int ib_ipath_max_mcast_grps; | ||
720 | |||
721 | extern unsigned int ib_ipath_max_mcast_qp_attached; | ||
722 | |||
723 | extern unsigned int ib_ipath_max_srqs; | ||
724 | |||
725 | extern unsigned int ib_ipath_max_srq_sges; | ||
726 | |||
727 | extern unsigned int ib_ipath_max_srq_wrs; | ||
728 | |||
691 | extern const u32 ib_ipath_rnr_table[]; | 729 | extern const u32 ib_ipath_rnr_table[]; |
692 | 730 | ||
693 | #endif /* IPATH_VERBS_H */ | 731 | #endif /* IPATH_VERBS_H */ |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c index 10b31d2c4f20..ee0e1d96d723 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
@@ -92,6 +93,7 @@ static struct ipath_mcast *ipath_mcast_alloc(union ib_gid *mgid) | |||
92 | INIT_LIST_HEAD(&mcast->qp_list); | 93 | INIT_LIST_HEAD(&mcast->qp_list); |
93 | init_waitqueue_head(&mcast->wait); | 94 | init_waitqueue_head(&mcast->wait); |
94 | atomic_set(&mcast->refcount, 0); | 95 | atomic_set(&mcast->refcount, 0); |
96 | mcast->n_attached = 0; | ||
95 | 97 | ||
96 | bail: | 98 | bail: |
97 | return mcast; | 99 | return mcast; |
@@ -157,7 +159,8 @@ bail: | |||
157 | * the table but the QP was added. Return ESRCH if the QP was already | 159 | * the table but the QP was added. Return ESRCH if the QP was already |
158 | * attached and neither structure was added. | 160 | * attached and neither structure was added. |
159 | */ | 161 | */ |
160 | static int ipath_mcast_add(struct ipath_mcast *mcast, | 162 | static int ipath_mcast_add(struct ipath_ibdev *dev, |
163 | struct ipath_mcast *mcast, | ||
161 | struct ipath_mcast_qp *mqp) | 164 | struct ipath_mcast_qp *mqp) |
162 | { | 165 | { |
163 | struct rb_node **n = &mcast_tree.rb_node; | 166 | struct rb_node **n = &mcast_tree.rb_node; |
@@ -188,34 +191,47 @@ static int ipath_mcast_add(struct ipath_mcast *mcast, | |||
188 | /* Search the QP list to see if this is already there. */ | 191 | /* Search the QP list to see if this is already there. */ |
189 | list_for_each_entry_rcu(p, &tmcast->qp_list, list) { | 192 | list_for_each_entry_rcu(p, &tmcast->qp_list, list) { |
190 | if (p->qp == mqp->qp) { | 193 | if (p->qp == mqp->qp) { |
191 | spin_unlock_irqrestore(&mcast_lock, flags); | ||
192 | ret = ESRCH; | 194 | ret = ESRCH; |
193 | goto bail; | 195 | goto bail; |
194 | } | 196 | } |
195 | } | 197 | } |
198 | if (tmcast->n_attached == ib_ipath_max_mcast_qp_attached) { | ||
199 | ret = ENOMEM; | ||
200 | goto bail; | ||
201 | } | ||
202 | |||
203 | tmcast->n_attached++; | ||
204 | |||
196 | list_add_tail_rcu(&mqp->list, &tmcast->qp_list); | 205 | list_add_tail_rcu(&mqp->list, &tmcast->qp_list); |
197 | spin_unlock_irqrestore(&mcast_lock, flags); | ||
198 | ret = EEXIST; | 206 | ret = EEXIST; |
199 | goto bail; | 207 | goto bail; |
200 | } | 208 | } |
201 | 209 | ||
210 | if (dev->n_mcast_grps_allocated == ib_ipath_max_mcast_grps) { | ||
211 | ret = ENOMEM; | ||
212 | goto bail; | ||
213 | } | ||
214 | |||
215 | dev->n_mcast_grps_allocated++; | ||
216 | |||
202 | list_add_tail_rcu(&mqp->list, &mcast->qp_list); | 217 | list_add_tail_rcu(&mqp->list, &mcast->qp_list); |
203 | 218 | ||
204 | atomic_inc(&mcast->refcount); | 219 | atomic_inc(&mcast->refcount); |
205 | rb_link_node(&mcast->rb_node, pn, n); | 220 | rb_link_node(&mcast->rb_node, pn, n); |
206 | rb_insert_color(&mcast->rb_node, &mcast_tree); | 221 | rb_insert_color(&mcast->rb_node, &mcast_tree); |
207 | 222 | ||
208 | spin_unlock_irqrestore(&mcast_lock, flags); | ||
209 | |||
210 | ret = 0; | 223 | ret = 0; |
211 | 224 | ||
212 | bail: | 225 | bail: |
226 | spin_unlock_irqrestore(&mcast_lock, flags); | ||
227 | |||
213 | return ret; | 228 | return ret; |
214 | } | 229 | } |
215 | 230 | ||
216 | int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | 231 | int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) |
217 | { | 232 | { |
218 | struct ipath_qp *qp = to_iqp(ibqp); | 233 | struct ipath_qp *qp = to_iqp(ibqp); |
234 | struct ipath_ibdev *dev = to_idev(ibqp->device); | ||
219 | struct ipath_mcast *mcast; | 235 | struct ipath_mcast *mcast; |
220 | struct ipath_mcast_qp *mqp; | 236 | struct ipath_mcast_qp *mqp; |
221 | int ret; | 237 | int ret; |
@@ -235,7 +251,7 @@ int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
235 | ret = -ENOMEM; | 251 | ret = -ENOMEM; |
236 | goto bail; | 252 | goto bail; |
237 | } | 253 | } |
238 | switch (ipath_mcast_add(mcast, mqp)) { | 254 | switch (ipath_mcast_add(dev, mcast, mqp)) { |
239 | case ESRCH: | 255 | case ESRCH: |
240 | /* Neither was used: can't attach the same QP twice. */ | 256 | /* Neither was used: can't attach the same QP twice. */ |
241 | ipath_mcast_qp_free(mqp); | 257 | ipath_mcast_qp_free(mqp); |
@@ -245,6 +261,12 @@ int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
245 | case EEXIST: /* The mcast wasn't used */ | 261 | case EEXIST: /* The mcast wasn't used */ |
246 | ipath_mcast_free(mcast); | 262 | ipath_mcast_free(mcast); |
247 | break; | 263 | break; |
264 | case ENOMEM: | ||
265 | /* Exceeded the maximum number of mcast groups. */ | ||
266 | ipath_mcast_qp_free(mqp); | ||
267 | ipath_mcast_free(mcast); | ||
268 | ret = -ENOMEM; | ||
269 | goto bail; | ||
248 | default: | 270 | default: |
249 | break; | 271 | break; |
250 | } | 272 | } |
@@ -258,6 +280,7 @@ bail: | |||
258 | int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | 280 | int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) |
259 | { | 281 | { |
260 | struct ipath_qp *qp = to_iqp(ibqp); | 282 | struct ipath_qp *qp = to_iqp(ibqp); |
283 | struct ipath_ibdev *dev = to_idev(ibqp->device); | ||
261 | struct ipath_mcast *mcast = NULL; | 284 | struct ipath_mcast *mcast = NULL; |
262 | struct ipath_mcast_qp *p, *tmp; | 285 | struct ipath_mcast_qp *p, *tmp; |
263 | struct rb_node *n; | 286 | struct rb_node *n; |
@@ -272,7 +295,7 @@ int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
272 | while (1) { | 295 | while (1) { |
273 | if (n == NULL) { | 296 | if (n == NULL) { |
274 | spin_unlock_irqrestore(&mcast_lock, flags); | 297 | spin_unlock_irqrestore(&mcast_lock, flags); |
275 | ret = 0; | 298 | ret = -EINVAL; |
276 | goto bail; | 299 | goto bail; |
277 | } | 300 | } |
278 | 301 | ||
@@ -296,6 +319,7 @@ int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
296 | * link until we are sure there are no list walkers. | 319 | * link until we are sure there are no list walkers. |
297 | */ | 320 | */ |
298 | list_del_rcu(&p->list); | 321 | list_del_rcu(&p->list); |
322 | mcast->n_attached--; | ||
299 | 323 | ||
300 | /* If this was the last attached QP, remove the GID too. */ | 324 | /* If this was the last attached QP, remove the GID too. */ |
301 | if (list_empty(&mcast->qp_list)) { | 325 | if (list_empty(&mcast->qp_list)) { |
@@ -319,6 +343,7 @@ int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
319 | atomic_dec(&mcast->refcount); | 343 | atomic_dec(&mcast->refcount); |
320 | wait_event(mcast->wait, !atomic_read(&mcast->refcount)); | 344 | wait_event(mcast->wait, !atomic_read(&mcast->refcount)); |
321 | ipath_mcast_free(mcast); | 345 | ipath_mcast_free(mcast); |
346 | dev->n_mcast_grps_allocated--; | ||
322 | } | 347 | } |
323 | 348 | ||
324 | ret = 0; | 349 | ret = 0; |
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c index adc5322f15c1..f8f9e2e8cbdd 100644 --- a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c +++ b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
diff --git a/drivers/infiniband/hw/ipath/ips_common.h b/drivers/infiniband/hw/ipath/ips_common.h deleted file mode 100644 index ab7cbbbfd03a..000000000000 --- a/drivers/infiniband/hw/ipath/ips_common.h +++ /dev/null | |||
@@ -1,263 +0,0 @@ | |||
1 | #ifndef IPS_COMMON_H | ||
2 | #define IPS_COMMON_H | ||
3 | /* | ||
4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | ||
5 | * | ||
6 | * This software is available to you under a choice of one of two | ||
7 | * licenses. You may choose to be licensed under the terms of the GNU | ||
8 | * General Public License (GPL) Version 2, available from the file | ||
9 | * COPYING in the main directory of this source tree, or the | ||
10 | * OpenIB.org BSD license below: | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or | ||
13 | * without modification, are permitted provided that the following | ||
14 | * conditions are met: | ||
15 | * | ||
16 | * - Redistributions of source code must retain the above | ||
17 | * copyright notice, this list of conditions and the following | ||
18 | * disclaimer. | ||
19 | * | ||
20 | * - Redistributions in binary form must reproduce the above | ||
21 | * copyright notice, this list of conditions and the following | ||
22 | * disclaimer in the documentation and/or other materials | ||
23 | * provided with the distribution. | ||
24 | * | ||
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
29 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
30 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
32 | * SOFTWARE. | ||
33 | */ | ||
34 | |||
35 | #include "ipath_common.h" | ||
36 | |||
37 | struct ipath_header { | ||
38 | /* | ||
39 | * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset - | ||
40 | * 14 bits before ECO change ~28 Dec 03. After that, Vers 4, | ||
41 | * Port 3, TID 11, offset 14. | ||
42 | */ | ||
43 | __le32 ver_port_tid_offset; | ||
44 | __le16 chksum; | ||
45 | __le16 pkt_flags; | ||
46 | }; | ||
47 | |||
48 | struct ips_message_header { | ||
49 | __be16 lrh[4]; | ||
50 | __be32 bth[3]; | ||
51 | /* fields below this point are in host byte order */ | ||
52 | struct ipath_header iph; | ||
53 | __u8 sub_opcode; | ||
54 | __u8 flags; | ||
55 | __u16 src_rank; | ||
56 | /* 24 bits. The upper 8 bit is available for other use */ | ||
57 | union { | ||
58 | struct { | ||
59 | unsigned ack_seq_num:24; | ||
60 | unsigned port:4; | ||
61 | unsigned unused:4; | ||
62 | }; | ||
63 | __u32 ack_seq_num_org; | ||
64 | }; | ||
65 | __u8 expected_tid_session_id; | ||
66 | __u8 tinylen; /* to aid MPI */ | ||
67 | union { | ||
68 | __u16 tag; /* to aid MPI */ | ||
69 | __u16 mqhdr; /* for PSM MQ */ | ||
70 | }; | ||
71 | union { | ||
72 | __u32 mpi[4]; /* to aid MPI */ | ||
73 | __u32 data[4]; | ||
74 | __u64 mq[2]; /* for PSM MQ */ | ||
75 | struct { | ||
76 | __u16 mtu; | ||
77 | __u8 major_ver; | ||
78 | __u8 minor_ver; | ||
79 | __u32 not_used; //free | ||
80 | __u32 run_id; | ||
81 | __u32 client_ver; | ||
82 | }; | ||
83 | }; | ||
84 | }; | ||
85 | |||
86 | struct ether_header { | ||
87 | __be16 lrh[4]; | ||
88 | __be32 bth[3]; | ||
89 | struct ipath_header iph; | ||
90 | __u8 sub_opcode; | ||
91 | __u8 cmd; | ||
92 | __be16 lid; | ||
93 | __u16 mac[3]; | ||
94 | __u8 frag_num; | ||
95 | __u8 seq_num; | ||
96 | __le32 len; | ||
97 | /* MUST be of word size due to PIO write requirements */ | ||
98 | __le32 csum; | ||
99 | __le16 csum_offset; | ||
100 | __le16 flags; | ||
101 | __u16 first_2_bytes; | ||
102 | __u8 unused[2]; /* currently unused */ | ||
103 | }; | ||
104 | |||
105 | /* | ||
106 | * The PIO buffer used for sending infinipath messages must only be written | ||
107 | * in 32-bit words, all the data must be written, and no writes can occur | ||
108 | * after the last word is written (which transfers "ownership" of the buffer | ||
109 | * to the chip and triggers the message to be sent). | ||
110 | * Since the Linux sk_buff structure can be recursive, non-aligned, and | ||
111 | * any number of bytes in each segment, we use the following structure | ||
112 | * to keep information about the overall state of the copy operation. | ||
113 | * This is used to save the information needed to store the checksum | ||
114 | * in the right place before sending the last word to the hardware and | ||
115 | * to buffer the last 0-3 bytes of non-word sized segments. | ||
116 | */ | ||
117 | struct copy_data_s { | ||
118 | struct ether_header *hdr; | ||
119 | /* addr of PIO buf to write csum to */ | ||
120 | __u32 __iomem *csum_pio; | ||
121 | __u32 __iomem *to; /* addr of PIO buf to write data to */ | ||
122 | __u32 device; /* which device to allocate PIO bufs from */ | ||
123 | __s32 error; /* set if there is an error. */ | ||
124 | __s32 extra; /* amount of data saved in u.buf below */ | ||
125 | __u32 len; /* total length to send in bytes */ | ||
126 | __u32 flen; /* frament length in words */ | ||
127 | __u32 csum; /* partial IP checksum */ | ||
128 | __u32 pos; /* position for partial checksum */ | ||
129 | __u32 offset; /* offset to where data currently starts */ | ||
130 | __s32 checksum_calc; /* set to 1 when csum has been calculated */ | ||
131 | struct sk_buff *skb; | ||
132 | union { | ||
133 | __u32 w; | ||
134 | __u8 buf[4]; | ||
135 | } u; | ||
136 | }; | ||
137 | |||
138 | /* IB - LRH header consts */ | ||
139 | #define IPS_LRH_GRH 0x0003 /* 1. word of IB LRH - next header: GRH */ | ||
140 | #define IPS_LRH_BTH 0x0002 /* 1. word of IB LRH - next header: BTH */ | ||
141 | |||
142 | #define IPS_OFFSET 0 | ||
143 | |||
144 | /* | ||
145 | * defines the cut-off point between the header queue and eager/expected | ||
146 | * TID queue | ||
147 | */ | ||
148 | #define NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE \ | ||
149 | ((sizeof(struct ips_message_header) - \ | ||
150 | offsetof(struct ips_message_header, iph)) >> 2) | ||
151 | |||
152 | /* OpCodes */ | ||
153 | #define OPCODE_IPS 0xC0 | ||
154 | #define OPCODE_ITH4X 0xC1 | ||
155 | |||
156 | /* OpCode 30 is use by stand-alone test programs */ | ||
157 | #define OPCODE_RAW_DATA 0xDE | ||
158 | /* last OpCode (31) is reserved for test */ | ||
159 | #define OPCODE_TEST 0xDF | ||
160 | |||
161 | /* sub OpCodes - ips */ | ||
162 | #define OPCODE_SEQ_DATA 0x01 | ||
163 | #define OPCODE_SEQ_CTRL 0x02 | ||
164 | |||
165 | #define OPCODE_SEQ_MQ_DATA 0x03 | ||
166 | #define OPCODE_SEQ_MQ_CTRL 0x04 | ||
167 | |||
168 | #define OPCODE_ACK 0x10 | ||
169 | #define OPCODE_NAK 0x11 | ||
170 | |||
171 | #define OPCODE_ERR_CHK 0x20 | ||
172 | #define OPCODE_ERR_CHK_PLS 0x21 | ||
173 | |||
174 | #define OPCODE_STARTUP 0x30 | ||
175 | #define OPCODE_STARTUP_ACK 0x31 | ||
176 | #define OPCODE_STARTUP_NAK 0x32 | ||
177 | |||
178 | #define OPCODE_STARTUP_EXT 0x34 | ||
179 | #define OPCODE_STARTUP_ACK_EXT 0x35 | ||
180 | #define OPCODE_STARTUP_NAK_EXT 0x36 | ||
181 | |||
182 | #define OPCODE_TIDS_RELEASE 0x40 | ||
183 | #define OPCODE_TIDS_RELEASE_CONFIRM 0x41 | ||
184 | |||
185 | #define OPCODE_CLOSE 0x50 | ||
186 | #define OPCODE_CLOSE_ACK 0x51 | ||
187 | /* | ||
188 | * like OPCODE_CLOSE, but no complaint if other side has already closed. | ||
189 | * Used when doing abort(), MPI_Abort(), etc. | ||
190 | */ | ||
191 | #define OPCODE_ABORT 0x52 | ||
192 | |||
193 | /* sub OpCodes - ith4x */ | ||
194 | #define OPCODE_ENCAP 0x81 | ||
195 | #define OPCODE_LID_ARP 0x82 | ||
196 | |||
197 | /* Receive Header Queue: receive type (from infinipath) */ | ||
198 | #define RCVHQ_RCV_TYPE_EXPECTED 0 | ||
199 | #define RCVHQ_RCV_TYPE_EAGER 1 | ||
200 | #define RCVHQ_RCV_TYPE_NON_KD 2 | ||
201 | #define RCVHQ_RCV_TYPE_ERROR 3 | ||
202 | |||
203 | /* misc. */ | ||
204 | #define SIZE_OF_CRC 1 | ||
205 | |||
206 | #define EAGER_TID_ID INFINIPATH_I_TID_MASK | ||
207 | |||
208 | #define IPS_DEFAULT_P_KEY 0xFFFF | ||
209 | |||
210 | #define IPS_PERMISSIVE_LID 0xFFFF | ||
211 | #define IPS_MULTICAST_LID_BASE 0xC000 | ||
212 | |||
213 | #define IPS_AETH_CREDIT_SHIFT 24 | ||
214 | #define IPS_AETH_CREDIT_MASK 0x1F | ||
215 | #define IPS_AETH_CREDIT_INVAL 0x1F | ||
216 | |||
217 | #define IPS_PSN_MASK 0xFFFFFF | ||
218 | #define IPS_MSN_MASK 0xFFFFFF | ||
219 | #define IPS_QPN_MASK 0xFFFFFF | ||
220 | #define IPS_MULTICAST_QPN 0xFFFFFF | ||
221 | |||
222 | /* functions for extracting fields from rcvhdrq entries */ | ||
223 | static inline __u32 ips_get_hdr_err_flags(const __le32 * rbuf) | ||
224 | { | ||
225 | return __le32_to_cpu(rbuf[1]); | ||
226 | } | ||
227 | |||
228 | static inline __u32 ips_get_index(const __le32 * rbuf) | ||
229 | { | ||
230 | return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_EGRINDEX_SHIFT) | ||
231 | & INFINIPATH_RHF_EGRINDEX_MASK; | ||
232 | } | ||
233 | |||
234 | static inline __u32 ips_get_rcv_type(const __le32 * rbuf) | ||
235 | { | ||
236 | return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_RCVTYPE_SHIFT) | ||
237 | & INFINIPATH_RHF_RCVTYPE_MASK; | ||
238 | } | ||
239 | |||
240 | static inline __u32 ips_get_length_in_bytes(const __le32 * rbuf) | ||
241 | { | ||
242 | return ((__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_LENGTH_SHIFT) | ||
243 | & INFINIPATH_RHF_LENGTH_MASK) << 2; | ||
244 | } | ||
245 | |||
246 | static inline void *ips_get_first_protocol_header(const __u32 * rbuf) | ||
247 | { | ||
248 | return (void *)&rbuf[2]; | ||
249 | } | ||
250 | |||
251 | static inline struct ips_message_header *ips_get_ips_header(const __u32 * | ||
252 | rbuf) | ||
253 | { | ||
254 | return (struct ips_message_header *)&rbuf[2]; | ||
255 | } | ||
256 | |||
257 | static inline __u32 ips_get_ipath_ver(__le32 hdrword) | ||
258 | { | ||
259 | return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT) | ||
260 | & INFINIPATH_I_VERS_MASK; | ||
261 | } | ||
262 | |||
263 | #endif /* IPS_COMMON_H */ | ||
diff --git a/drivers/infiniband/hw/ipath/verbs_debug.h b/drivers/infiniband/hw/ipath/verbs_debug.h index 40d693cf3f94..6186676f2a16 100644 --- a/drivers/infiniband/hw/ipath/verbs_debug.h +++ b/drivers/infiniband/hw/ipath/verbs_debug.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006 QLogic, Inc. All rights reserved. | ||
2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
3 | * | 4 | * |
4 | * This software is available to you under a choice of one of two | 5 | * This software is available to you under a choice of one of two |
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index e7cf6bec737e..9fefe563f8fc 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
@@ -395,7 +395,8 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) | |||
395 | /* check if the resource is already in use, skip if the | 395 | /* check if the resource is already in use, skip if the |
396 | * device is active because it itself may be in use */ | 396 | * device is active because it itself may be in use */ |
397 | if(!dev->active) { | 397 | if(!dev->active) { |
398 | if (request_irq(*irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL)) | 398 | if (request_irq(*irq, pnp_test_handler, |
399 | SA_INTERRUPT|SA_PROBEIRQ, "pnp", NULL)) | ||
399 | return 0; | 400 | return 0; |
400 | free_irq(*irq, NULL); | 401 | free_irq(*irq, NULL); |
401 | } | 402 | } |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index d51afbe014e5..f5b9f187a930 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -182,6 +182,22 @@ config RTC_DRV_RS5C372 | |||
182 | This driver can also be built as a module. If so, the module | 182 | This driver can also be built as a module. If so, the module |
183 | will be called rtc-rs5c372. | 183 | will be called rtc-rs5c372. |
184 | 184 | ||
185 | config RTC_DRV_S3C | ||
186 | tristate "Samsung S3C series SoC RTC" | ||
187 | depends on RTC_CLASS && ARCH_S3C2410 | ||
188 | help | ||
189 | RTC (Realtime Clock) driver for the clock inbuilt into the | ||
190 | Samsung S3C24XX series of SoCs. This can provide periodic | ||
191 | interrupt rates from 1Hz to 64Hz for user programs, and | ||
192 | wakeup from Alarm. | ||
193 | |||
194 | The driver currently supports the common features on all the | ||
195 | S3C24XX range, such as the S3C2410, S3C2412, S3C2413, S3C2440 | ||
196 | and S3C2442. | ||
197 | |||
198 | This driver can also be build as a module. If so, the module | ||
199 | will be called rtc-s3c. | ||
200 | |||
185 | config RTC_DRV_M48T86 | 201 | config RTC_DRV_M48T86 |
186 | tristate "ST M48T86/Dallas DS12887" | 202 | tristate "ST M48T86/Dallas DS12887" |
187 | depends on RTC_CLASS | 203 | depends on RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index da5e38774e13..54220714ff49 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | |||
19 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 19 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
20 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 20 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
21 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 21 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
22 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o | ||
22 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 23 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
23 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 24 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
24 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 25 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c new file mode 100644 index 000000000000..d6d1bff52b8e --- /dev/null +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -0,0 +1,607 @@ | |||
1 | /* drivers/rtc/rtc-s3c.c | ||
2 | * | ||
3 | * Copyright (c) 2004,2006 Simtec Electronics | ||
4 | * Ben Dooks, <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
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 | * S3C2410/S3C2440/S3C24XX Internal RTC Driver | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/bcd.h> | ||
22 | #include <linux/clk.h> | ||
23 | |||
24 | #include <asm/hardware.h> | ||
25 | #include <asm/uaccess.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/irq.h> | ||
28 | #include <asm/rtc.h> | ||
29 | |||
30 | #include <asm/mach/time.h> | ||
31 | |||
32 | #include <asm/arch/regs-rtc.h> | ||
33 | |||
34 | /* I have yet to find an S3C implementation with more than one | ||
35 | * of these rtc blocks in */ | ||
36 | |||
37 | static struct resource *s3c_rtc_mem; | ||
38 | |||
39 | static void __iomem *s3c_rtc_base; | ||
40 | static int s3c_rtc_alarmno = NO_IRQ; | ||
41 | static int s3c_rtc_tickno = NO_IRQ; | ||
42 | static int s3c_rtc_freq = 1; | ||
43 | |||
44 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | ||
45 | static unsigned int tick_count; | ||
46 | |||
47 | /* IRQ Handlers */ | ||
48 | |||
49 | static irqreturn_t s3c_rtc_alarmirq(int irq, void *id, struct pt_regs *r) | ||
50 | { | ||
51 | struct rtc_device *rdev = id; | ||
52 | |||
53 | rtc_update_irq(&rdev->class_dev, 1, RTC_AF | RTC_IRQF); | ||
54 | return IRQ_HANDLED; | ||
55 | } | ||
56 | |||
57 | static irqreturn_t s3c_rtc_tickirq(int irq, void *id, struct pt_regs *r) | ||
58 | { | ||
59 | struct rtc_device *rdev = id; | ||
60 | |||
61 | rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF); | ||
62 | return IRQ_HANDLED; | ||
63 | } | ||
64 | |||
65 | /* Update control registers */ | ||
66 | static void s3c_rtc_setaie(int to) | ||
67 | { | ||
68 | unsigned int tmp; | ||
69 | |||
70 | pr_debug("%s: aie=%d\n", __FUNCTION__, to); | ||
71 | |||
72 | tmp = readb(S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; | ||
73 | |||
74 | if (to) | ||
75 | tmp |= S3C2410_RTCALM_ALMEN; | ||
76 | |||
77 | writeb(tmp, S3C2410_RTCALM); | ||
78 | } | ||
79 | |||
80 | static void s3c_rtc_setpie(int to) | ||
81 | { | ||
82 | unsigned int tmp; | ||
83 | |||
84 | pr_debug("%s: pie=%d\n", __FUNCTION__, to); | ||
85 | |||
86 | spin_lock_irq(&s3c_rtc_pie_lock); | ||
87 | tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; | ||
88 | |||
89 | if (to) | ||
90 | tmp |= S3C2410_TICNT_ENABLE; | ||
91 | |||
92 | writeb(tmp, S3C2410_TICNT); | ||
93 | spin_unlock_irq(&s3c_rtc_pie_lock); | ||
94 | } | ||
95 | |||
96 | static void s3c_rtc_setfreq(int freq) | ||
97 | { | ||
98 | unsigned int tmp; | ||
99 | |||
100 | spin_lock_irq(&s3c_rtc_pie_lock); | ||
101 | tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE; | ||
102 | |||
103 | s3c_rtc_freq = freq; | ||
104 | |||
105 | tmp |= (128 / freq)-1; | ||
106 | |||
107 | writeb(tmp, S3C2410_TICNT); | ||
108 | spin_unlock_irq(&s3c_rtc_pie_lock); | ||
109 | } | ||
110 | |||
111 | /* Time read/write */ | ||
112 | |||
113 | static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | ||
114 | { | ||
115 | unsigned int have_retried = 0; | ||
116 | |||
117 | retry_get_time: | ||
118 | rtc_tm->tm_min = readb(S3C2410_RTCMIN); | ||
119 | rtc_tm->tm_hour = readb(S3C2410_RTCHOUR); | ||
120 | rtc_tm->tm_mday = readb(S3C2410_RTCDATE); | ||
121 | rtc_tm->tm_mon = readb(S3C2410_RTCMON); | ||
122 | rtc_tm->tm_year = readb(S3C2410_RTCYEAR); | ||
123 | rtc_tm->tm_sec = readb(S3C2410_RTCSEC); | ||
124 | |||
125 | /* the only way to work out wether the system was mid-update | ||
126 | * when we read it is to check the second counter, and if it | ||
127 | * is zero, then we re-try the entire read | ||
128 | */ | ||
129 | |||
130 | if (rtc_tm->tm_sec == 0 && !have_retried) { | ||
131 | have_retried = 1; | ||
132 | goto retry_get_time; | ||
133 | } | ||
134 | |||
135 | pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", | ||
136 | rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | ||
137 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | ||
138 | |||
139 | BCD_TO_BIN(rtc_tm->tm_sec); | ||
140 | BCD_TO_BIN(rtc_tm->tm_min); | ||
141 | BCD_TO_BIN(rtc_tm->tm_hour); | ||
142 | BCD_TO_BIN(rtc_tm->tm_mday); | ||
143 | BCD_TO_BIN(rtc_tm->tm_mon); | ||
144 | BCD_TO_BIN(rtc_tm->tm_year); | ||
145 | |||
146 | rtc_tm->tm_year += 100; | ||
147 | rtc_tm->tm_mon -= 1; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | ||
153 | { | ||
154 | /* the rtc gets round the y2k problem by just not supporting it */ | ||
155 | |||
156 | if (tm->tm_year < 100) | ||
157 | return -EINVAL; | ||
158 | |||
159 | writeb(BIN2BCD(tm->tm_sec), S3C2410_RTCSEC); | ||
160 | writeb(BIN2BCD(tm->tm_min), S3C2410_RTCMIN); | ||
161 | writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR); | ||
162 | writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE); | ||
163 | writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON); | ||
164 | writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
170 | { | ||
171 | struct rtc_time *alm_tm = &alrm->time; | ||
172 | unsigned int alm_en; | ||
173 | |||
174 | alm_tm->tm_sec = readb(S3C2410_ALMSEC); | ||
175 | alm_tm->tm_min = readb(S3C2410_ALMMIN); | ||
176 | alm_tm->tm_hour = readb(S3C2410_ALMHOUR); | ||
177 | alm_tm->tm_mon = readb(S3C2410_ALMMON); | ||
178 | alm_tm->tm_mday = readb(S3C2410_ALMDATE); | ||
179 | alm_tm->tm_year = readb(S3C2410_ALMYEAR); | ||
180 | |||
181 | alm_en = readb(S3C2410_RTCALM); | ||
182 | |||
183 | pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", | ||
184 | alm_en, | ||
185 | alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, | ||
186 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); | ||
187 | |||
188 | |||
189 | /* decode the alarm enable field */ | ||
190 | |||
191 | if (alm_en & S3C2410_RTCALM_SECEN) | ||
192 | BCD_TO_BIN(alm_tm->tm_sec); | ||
193 | else | ||
194 | alm_tm->tm_sec = 0xff; | ||
195 | |||
196 | if (alm_en & S3C2410_RTCALM_MINEN) | ||
197 | BCD_TO_BIN(alm_tm->tm_min); | ||
198 | else | ||
199 | alm_tm->tm_min = 0xff; | ||
200 | |||
201 | if (alm_en & S3C2410_RTCALM_HOUREN) | ||
202 | BCD_TO_BIN(alm_tm->tm_hour); | ||
203 | else | ||
204 | alm_tm->tm_hour = 0xff; | ||
205 | |||
206 | if (alm_en & S3C2410_RTCALM_DAYEN) | ||
207 | BCD_TO_BIN(alm_tm->tm_mday); | ||
208 | else | ||
209 | alm_tm->tm_mday = 0xff; | ||
210 | |||
211 | if (alm_en & S3C2410_RTCALM_MONEN) { | ||
212 | BCD_TO_BIN(alm_tm->tm_mon); | ||
213 | alm_tm->tm_mon -= 1; | ||
214 | } else { | ||
215 | alm_tm->tm_mon = 0xff; | ||
216 | } | ||
217 | |||
218 | if (alm_en & S3C2410_RTCALM_YEAREN) | ||
219 | BCD_TO_BIN(alm_tm->tm_year); | ||
220 | else | ||
221 | alm_tm->tm_year = 0xffff; | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
227 | { | ||
228 | struct rtc_time *tm = &alrm->time; | ||
229 | unsigned int alrm_en; | ||
230 | |||
231 | pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", | ||
232 | alrm->enabled, | ||
233 | tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, | ||
234 | tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); | ||
235 | |||
236 | |||
237 | alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; | ||
238 | writeb(0x00, S3C2410_RTCALM); | ||
239 | |||
240 | if (tm->tm_sec < 60 && tm->tm_sec >= 0) { | ||
241 | alrm_en |= S3C2410_RTCALM_SECEN; | ||
242 | writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC); | ||
243 | } | ||
244 | |||
245 | if (tm->tm_min < 60 && tm->tm_min >= 0) { | ||
246 | alrm_en |= S3C2410_RTCALM_MINEN; | ||
247 | writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN); | ||
248 | } | ||
249 | |||
250 | if (tm->tm_hour < 24 && tm->tm_hour >= 0) { | ||
251 | alrm_en |= S3C2410_RTCALM_HOUREN; | ||
252 | writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR); | ||
253 | } | ||
254 | |||
255 | pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); | ||
256 | |||
257 | writeb(alrm_en, S3C2410_RTCALM); | ||
258 | |||
259 | if (0) { | ||
260 | alrm_en = readb(S3C2410_RTCALM); | ||
261 | alrm_en &= ~S3C2410_RTCALM_ALMEN; | ||
262 | writeb(alrm_en, S3C2410_RTCALM); | ||
263 | disable_irq_wake(s3c_rtc_alarmno); | ||
264 | } | ||
265 | |||
266 | if (alrm->enabled) | ||
267 | enable_irq_wake(s3c_rtc_alarmno); | ||
268 | else | ||
269 | disable_irq_wake(s3c_rtc_alarmno); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int s3c_rtc_ioctl(struct device *dev, | ||
275 | unsigned int cmd, unsigned long arg) | ||
276 | { | ||
277 | unsigned int ret = -ENOIOCTLCMD; | ||
278 | |||
279 | switch (cmd) { | ||
280 | case RTC_AIE_OFF: | ||
281 | case RTC_AIE_ON: | ||
282 | s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0); | ||
283 | ret = 0; | ||
284 | break; | ||
285 | |||
286 | case RTC_PIE_OFF: | ||
287 | case RTC_PIE_ON: | ||
288 | tick_count = 0; | ||
289 | s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0); | ||
290 | ret = 0; | ||
291 | break; | ||
292 | |||
293 | case RTC_IRQP_READ: | ||
294 | ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg); | ||
295 | break; | ||
296 | |||
297 | case RTC_IRQP_SET: | ||
298 | /* check for power of 2 */ | ||
299 | |||
300 | if ((arg & (arg-1)) != 0 || arg < 1) { | ||
301 | ret = -EINVAL; | ||
302 | goto exit; | ||
303 | } | ||
304 | |||
305 | pr_debug("s3c2410_rtc: setting frequency %ld\n", arg); | ||
306 | |||
307 | s3c_rtc_setfreq(arg); | ||
308 | ret = 0; | ||
309 | break; | ||
310 | |||
311 | case RTC_UIE_ON: | ||
312 | case RTC_UIE_OFF: | ||
313 | ret = -EINVAL; | ||
314 | } | ||
315 | |||
316 | exit: | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | ||
321 | { | ||
322 | unsigned int rtcalm = readb(S3C2410_RTCALM); | ||
323 | unsigned int ticnt = readb (S3C2410_TICNT); | ||
324 | |||
325 | seq_printf(seq, "alarm_IRQ\t: %s\n", | ||
326 | (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" ); | ||
327 | |||
328 | seq_printf(seq, "periodic_IRQ\t: %s\n", | ||
329 | (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); | ||
330 | |||
331 | seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int s3c_rtc_open(struct device *dev) | ||
337 | { | ||
338 | struct platform_device *pdev = to_platform_device(dev); | ||
339 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
340 | int ret; | ||
341 | |||
342 | ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, | ||
343 | SA_INTERRUPT, "s3c2410-rtc alarm", rtc_dev); | ||
344 | |||
345 | if (ret) { | ||
346 | dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, | ||
351 | SA_INTERRUPT, "s3c2410-rtc tick", rtc_dev); | ||
352 | |||
353 | if (ret) { | ||
354 | dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); | ||
355 | goto tick_err; | ||
356 | } | ||
357 | |||
358 | return ret; | ||
359 | |||
360 | tick_err: | ||
361 | free_irq(s3c_rtc_alarmno, rtc_dev); | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static void s3c_rtc_release(struct device *dev) | ||
366 | { | ||
367 | struct platform_device *pdev = to_platform_device(dev); | ||
368 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
369 | |||
370 | /* do not clear AIE here, it may be needed for wake */ | ||
371 | |||
372 | s3c_rtc_setpie(0); | ||
373 | free_irq(s3c_rtc_alarmno, rtc_dev); | ||
374 | free_irq(s3c_rtc_tickno, rtc_dev); | ||
375 | } | ||
376 | |||
377 | static struct rtc_class_ops s3c_rtcops = { | ||
378 | .open = s3c_rtc_open, | ||
379 | .release = s3c_rtc_release, | ||
380 | .ioctl = s3c_rtc_ioctl, | ||
381 | .read_time = s3c_rtc_gettime, | ||
382 | .set_time = s3c_rtc_settime, | ||
383 | .read_alarm = s3c_rtc_getalarm, | ||
384 | .set_alarm = s3c_rtc_setalarm, | ||
385 | .proc = s3c_rtc_proc, | ||
386 | }; | ||
387 | |||
388 | static void s3c_rtc_enable(struct platform_device *pdev, int en) | ||
389 | { | ||
390 | unsigned int tmp; | ||
391 | |||
392 | if (s3c_rtc_base == NULL) | ||
393 | return; | ||
394 | |||
395 | if (!en) { | ||
396 | tmp = readb(S3C2410_RTCCON); | ||
397 | writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON); | ||
398 | |||
399 | tmp = readb(S3C2410_TICNT); | ||
400 | writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT); | ||
401 | } else { | ||
402 | /* re-enable the device, and check it is ok */ | ||
403 | |||
404 | if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ | ||
405 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); | ||
406 | |||
407 | tmp = readb(S3C2410_RTCCON); | ||
408 | writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON); | ||
409 | } | ||
410 | |||
411 | if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ | ||
412 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); | ||
413 | |||
414 | tmp = readb(S3C2410_RTCCON); | ||
415 | writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON); | ||
416 | } | ||
417 | |||
418 | if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ | ||
419 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); | ||
420 | |||
421 | tmp = readb(S3C2410_RTCCON); | ||
422 | writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON); | ||
423 | } | ||
424 | } | ||
425 | } | ||
426 | |||
427 | static int s3c_rtc_remove(struct platform_device *dev) | ||
428 | { | ||
429 | struct rtc_device *rtc = platform_get_drvdata(dev); | ||
430 | |||
431 | platform_set_drvdata(dev, NULL); | ||
432 | rtc_device_unregister(rtc); | ||
433 | |||
434 | s3c_rtc_setpie(0); | ||
435 | s3c_rtc_setaie(0); | ||
436 | |||
437 | iounmap(s3c_rtc_base); | ||
438 | release_resource(s3c_rtc_mem); | ||
439 | kfree(s3c_rtc_mem); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static int s3c_rtc_probe(struct platform_device *pdev) | ||
445 | { | ||
446 | struct rtc_device *rtc; | ||
447 | struct resource *res; | ||
448 | int ret; | ||
449 | |||
450 | pr_debug("%s: probe=%p\n", __FUNCTION__, pdev); | ||
451 | |||
452 | /* find the IRQs */ | ||
453 | |||
454 | s3c_rtc_tickno = platform_get_irq(pdev, 1); | ||
455 | if (s3c_rtc_tickno < 0) { | ||
456 | dev_err(&pdev->dev, "no irq for rtc tick\n"); | ||
457 | return -ENOENT; | ||
458 | } | ||
459 | |||
460 | s3c_rtc_alarmno = platform_get_irq(pdev, 0); | ||
461 | if (s3c_rtc_alarmno < 0) { | ||
462 | dev_err(&pdev->dev, "no irq for alarm\n"); | ||
463 | return -ENOENT; | ||
464 | } | ||
465 | |||
466 | pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n", | ||
467 | s3c_rtc_tickno, s3c_rtc_alarmno); | ||
468 | |||
469 | /* get the memory region */ | ||
470 | |||
471 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
472 | if (res == NULL) { | ||
473 | dev_err(&pdev->dev, "failed to get memory region resource\n"); | ||
474 | return -ENOENT; | ||
475 | } | ||
476 | |||
477 | s3c_rtc_mem = request_mem_region(res->start, | ||
478 | res->end-res->start+1, | ||
479 | pdev->name); | ||
480 | |||
481 | if (s3c_rtc_mem == NULL) { | ||
482 | dev_err(&pdev->dev, "failed to reserve memory region\n"); | ||
483 | ret = -ENOENT; | ||
484 | goto err_nores; | ||
485 | } | ||
486 | |||
487 | s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); | ||
488 | if (s3c_rtc_base == NULL) { | ||
489 | dev_err(&pdev->dev, "failed ioremap()\n"); | ||
490 | ret = -EINVAL; | ||
491 | goto err_nomap; | ||
492 | } | ||
493 | |||
494 | /* check to see if everything is setup correctly */ | ||
495 | |||
496 | s3c_rtc_enable(pdev, 1); | ||
497 | |||
498 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON)); | ||
499 | |||
500 | s3c_rtc_setfreq(s3c_rtc_freq); | ||
501 | |||
502 | /* register RTC and exit */ | ||
503 | |||
504 | rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops, | ||
505 | THIS_MODULE); | ||
506 | |||
507 | if (IS_ERR(rtc)) { | ||
508 | dev_err(&pdev->dev, "cannot attach rtc\n"); | ||
509 | ret = PTR_ERR(rtc); | ||
510 | goto err_nortc; | ||
511 | } | ||
512 | |||
513 | rtc->max_user_freq = 128; | ||
514 | |||
515 | platform_set_drvdata(pdev, rtc); | ||
516 | return 0; | ||
517 | |||
518 | err_nortc: | ||
519 | s3c_rtc_enable(pdev, 0); | ||
520 | iounmap(s3c_rtc_base); | ||
521 | |||
522 | err_nomap: | ||
523 | release_resource(s3c_rtc_mem); | ||
524 | |||
525 | err_nores: | ||
526 | return ret; | ||
527 | } | ||
528 | |||
529 | #ifdef CONFIG_PM | ||
530 | |||
531 | /* RTC Power management control */ | ||
532 | |||
533 | static struct timespec s3c_rtc_delta; | ||
534 | |||
535 | static int ticnt_save; | ||
536 | |||
537 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
538 | { | ||
539 | struct rtc_time tm; | ||
540 | struct timespec time; | ||
541 | |||
542 | time.tv_nsec = 0; | ||
543 | |||
544 | /* save TICNT for anyone using periodic interrupts */ | ||
545 | |||
546 | ticnt_save = readb(S3C2410_TICNT); | ||
547 | |||
548 | /* calculate time delta for suspend */ | ||
549 | |||
550 | s3c_rtc_gettime(&pdev->dev, &tm); | ||
551 | rtc_tm_to_time(&tm, &time.tv_sec); | ||
552 | save_time_delta(&s3c_rtc_delta, &time); | ||
553 | s3c_rtc_enable(pdev, 0); | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static int s3c_rtc_resume(struct platform_device *pdev) | ||
559 | { | ||
560 | struct rtc_time tm; | ||
561 | struct timespec time; | ||
562 | |||
563 | time.tv_nsec = 0; | ||
564 | |||
565 | s3c_rtc_enable(pdev, 1); | ||
566 | s3c_rtc_gettime(&pdev->dev, &tm); | ||
567 | rtc_tm_to_time(&tm, &time.tv_sec); | ||
568 | restore_time_delta(&s3c_rtc_delta, &time); | ||
569 | |||
570 | writeb(ticnt_save, S3C2410_TICNT); | ||
571 | return 0; | ||
572 | } | ||
573 | #else | ||
574 | #define s3c_rtc_suspend NULL | ||
575 | #define s3c_rtc_resume NULL | ||
576 | #endif | ||
577 | |||
578 | static struct platform_driver s3c2410_rtcdrv = { | ||
579 | .probe = s3c_rtc_probe, | ||
580 | .remove = s3c_rtc_remove, | ||
581 | .suspend = s3c_rtc_suspend, | ||
582 | .resume = s3c_rtc_resume, | ||
583 | .driver = { | ||
584 | .name = "s3c2410-rtc", | ||
585 | .owner = THIS_MODULE, | ||
586 | }, | ||
587 | }; | ||
588 | |||
589 | static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n"; | ||
590 | |||
591 | static int __init s3c_rtc_init(void) | ||
592 | { | ||
593 | printk(banner); | ||
594 | return platform_driver_register(&s3c2410_rtcdrv); | ||
595 | } | ||
596 | |||
597 | static void __exit s3c_rtc_exit(void) | ||
598 | { | ||
599 | platform_driver_unregister(&s3c2410_rtcdrv); | ||
600 | } | ||
601 | |||
602 | module_init(s3c_rtc_init); | ||
603 | module_exit(s3c_rtc_exit); | ||
604 | |||
605 | MODULE_DESCRIPTION("Samsung S3C RTC Driver"); | ||
606 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
607 | MODULE_LICENSE("GPL"); | ||
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 477eaa2fcf6a..12dfdcfbee3d 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -2932,6 +2932,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
2932 | } | 2932 | } |
2933 | if (error) | 2933 | if (error) |
2934 | goto out; | 2934 | goto out; |
2935 | /* | ||
2936 | * file size is changed, ctime and mtime are | ||
2937 | * to be updated | ||
2938 | */ | ||
2939 | attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME); | ||
2935 | } | 2940 | } |
2936 | } | 2941 | } |
2937 | 2942 | ||
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 95b878e5c7a0..b01804baa120 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
@@ -217,48 +217,6 @@ failed: | |||
217 | return; | 217 | return; |
218 | } | 218 | } |
219 | 219 | ||
220 | static struct page *ufs_get_locked_page(struct address_space *mapping, | ||
221 | unsigned long index) | ||
222 | { | ||
223 | struct page *page; | ||
224 | |||
225 | try_again: | ||
226 | page = find_lock_page(mapping, index); | ||
227 | if (!page) { | ||
228 | page = read_cache_page(mapping, index, | ||
229 | (filler_t*)mapping->a_ops->readpage, | ||
230 | NULL); | ||
231 | if (IS_ERR(page)) { | ||
232 | printk(KERN_ERR "ufs_change_blocknr: " | ||
233 | "read_cache_page error: ino %lu, index: %lu\n", | ||
234 | mapping->host->i_ino, index); | ||
235 | goto out; | ||
236 | } | ||
237 | |||
238 | lock_page(page); | ||
239 | |||
240 | if (!PageUptodate(page) || PageError(page)) { | ||
241 | unlock_page(page); | ||
242 | page_cache_release(page); | ||
243 | |||
244 | printk(KERN_ERR "ufs_change_blocknr: " | ||
245 | "can not read page: ino %lu, index: %lu\n", | ||
246 | mapping->host->i_ino, index); | ||
247 | |||
248 | page = ERR_PTR(-EIO); | ||
249 | goto out; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | if (unlikely(!page->mapping || !page_has_buffers(page))) { | ||
254 | unlock_page(page); | ||
255 | page_cache_release(page); | ||
256 | goto try_again;/*we really need these buffers*/ | ||
257 | } | ||
258 | out: | ||
259 | return page; | ||
260 | } | ||
261 | |||
262 | /* | 220 | /* |
263 | * Modify inode page cache in such way: | 221 | * Modify inode page cache in such way: |
264 | * have - blocks with b_blocknr equal to oldb...oldb+count-1 | 222 | * have - blocks with b_blocknr equal to oldb...oldb+count-1 |
@@ -311,10 +269,8 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, | |||
311 | 269 | ||
312 | set_page_dirty(page); | 270 | set_page_dirty(page); |
313 | 271 | ||
314 | if (likely(cur_index != index)) { | 272 | if (likely(cur_index != index)) |
315 | unlock_page(page); | 273 | ufs_put_locked_page(page); |
316 | page_cache_release(page); | ||
317 | } | ||
318 | } | 274 | } |
319 | UFSD("EXIT\n"); | 275 | UFSD("EXIT\n"); |
320 | } | 276 | } |
diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 0e5001512a9d..a9c6e5f04fae 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c | |||
@@ -60,7 +60,3 @@ const struct file_operations ufs_file_operations = { | |||
60 | .fsync = ufs_sync_file, | 60 | .fsync = ufs_sync_file, |
61 | .sendfile = generic_file_sendfile, | 61 | .sendfile = generic_file_sendfile, |
62 | }; | 62 | }; |
63 | |||
64 | struct inode_operations ufs_file_inode_operations = { | ||
65 | .truncate = ufs_truncate, | ||
66 | }; | ||
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 488b5ff48afb..e7c8615beb65 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -843,14 +843,17 @@ int ufs_sync_inode (struct inode *inode) | |||
843 | 843 | ||
844 | void ufs_delete_inode (struct inode * inode) | 844 | void ufs_delete_inode (struct inode * inode) |
845 | { | 845 | { |
846 | loff_t old_i_size; | ||
847 | |||
846 | truncate_inode_pages(&inode->i_data, 0); | 848 | truncate_inode_pages(&inode->i_data, 0); |
847 | /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ | 849 | /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ |
848 | lock_kernel(); | 850 | lock_kernel(); |
849 | mark_inode_dirty(inode); | 851 | mark_inode_dirty(inode); |
850 | ufs_update_inode(inode, IS_SYNC(inode)); | 852 | ufs_update_inode(inode, IS_SYNC(inode)); |
853 | old_i_size = inode->i_size; | ||
851 | inode->i_size = 0; | 854 | inode->i_size = 0; |
852 | if (inode->i_blocks) | 855 | if (inode->i_blocks && ufs_truncate(inode, old_i_size)) |
853 | ufs_truncate (inode); | 856 | ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); |
854 | ufs_free_inode (inode); | 857 | ufs_free_inode (inode); |
855 | unlock_kernel(); | 858 | unlock_kernel(); |
856 | } | 859 | } |
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 3c3b301f8701..c9b55872079b 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c | |||
@@ -369,24 +369,97 @@ static int ufs_trunc_tindirect (struct inode * inode) | |||
369 | UFSD("EXIT\n"); | 369 | UFSD("EXIT\n"); |
370 | return retry; | 370 | return retry; |
371 | } | 371 | } |
372 | 372 | ||
373 | void ufs_truncate (struct inode * inode) | 373 | static int ufs_alloc_lastblock(struct inode *inode) |
374 | { | 374 | { |
375 | int err = 0; | ||
376 | struct address_space *mapping = inode->i_mapping; | ||
377 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; | ||
375 | struct ufs_inode_info *ufsi = UFS_I(inode); | 378 | struct ufs_inode_info *ufsi = UFS_I(inode); |
376 | struct super_block * sb; | 379 | unsigned lastfrag, i, end; |
377 | struct ufs_sb_private_info * uspi; | 380 | struct page *lastpage; |
378 | int retry; | 381 | struct buffer_head *bh; |
382 | |||
383 | lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; | ||
384 | |||
385 | if (!lastfrag) { | ||
386 | ufsi->i_lastfrag = 0; | ||
387 | goto out; | ||
388 | } | ||
389 | lastfrag--; | ||
390 | |||
391 | lastpage = ufs_get_locked_page(mapping, lastfrag >> | ||
392 | (PAGE_CACHE_SHIFT - inode->i_blkbits)); | ||
393 | if (IS_ERR(lastpage)) { | ||
394 | err = -EIO; | ||
395 | goto out; | ||
396 | } | ||
397 | |||
398 | end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1); | ||
399 | bh = page_buffers(lastpage); | ||
400 | for (i = 0; i < end; ++i) | ||
401 | bh = bh->b_this_page; | ||
402 | |||
403 | if (!buffer_mapped(bh)) { | ||
404 | err = ufs_getfrag_block(inode, lastfrag, bh, 1); | ||
405 | |||
406 | if (unlikely(err)) | ||
407 | goto out_unlock; | ||
408 | |||
409 | if (buffer_new(bh)) { | ||
410 | clear_buffer_new(bh); | ||
411 | unmap_underlying_metadata(bh->b_bdev, | ||
412 | bh->b_blocknr); | ||
413 | /* | ||
414 | * we do not zeroize fragment, because of | ||
415 | * if it maped to hole, it already contains zeroes | ||
416 | */ | ||
417 | set_buffer_uptodate(bh); | ||
418 | mark_buffer_dirty(bh); | ||
419 | set_page_dirty(lastpage); | ||
420 | } | ||
421 | } | ||
422 | out_unlock: | ||
423 | ufs_put_locked_page(lastpage); | ||
424 | out: | ||
425 | return err; | ||
426 | } | ||
427 | |||
428 | int ufs_truncate(struct inode *inode, loff_t old_i_size) | ||
429 | { | ||
430 | struct ufs_inode_info *ufsi = UFS_I(inode); | ||
431 | struct super_block *sb = inode->i_sb; | ||
432 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
433 | int retry, err = 0; | ||
379 | 434 | ||
380 | UFSD("ENTER\n"); | 435 | UFSD("ENTER\n"); |
381 | sb = inode->i_sb; | ||
382 | uspi = UFS_SB(sb)->s_uspi; | ||
383 | 436 | ||
384 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) | 437 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
385 | return; | 438 | S_ISLNK(inode->i_mode))) |
439 | return -EINVAL; | ||
386 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | 440 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) |
387 | return; | 441 | return -EPERM; |
442 | |||
443 | if (inode->i_size > old_i_size) { | ||
444 | /* | ||
445 | * if we expand file we should care about | ||
446 | * allocation of block for last byte first of all | ||
447 | */ | ||
448 | err = ufs_alloc_lastblock(inode); | ||
449 | |||
450 | if (err) { | ||
451 | i_size_write(inode, old_i_size); | ||
452 | goto out; | ||
453 | } | ||
454 | /* | ||
455 | * go away, because of we expand file, and we do not | ||
456 | * need free blocks, and zeroizes page | ||
457 | */ | ||
458 | lock_kernel(); | ||
459 | goto almost_end; | ||
460 | } | ||
388 | 461 | ||
389 | block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); | 462 | block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); |
390 | 463 | ||
391 | lock_kernel(); | 464 | lock_kernel(); |
392 | while (1) { | 465 | while (1) { |
@@ -404,9 +477,58 @@ void ufs_truncate (struct inode * inode) | |||
404 | yield(); | 477 | yield(); |
405 | } | 478 | } |
406 | 479 | ||
480 | if (inode->i_size < old_i_size) { | ||
481 | /* | ||
482 | * now we should have enough space | ||
483 | * to allocate block for last byte | ||
484 | */ | ||
485 | err = ufs_alloc_lastblock(inode); | ||
486 | if (err) | ||
487 | /* | ||
488 | * looks like all the same - we have no space, | ||
489 | * but we truncate file already | ||
490 | */ | ||
491 | inode->i_size = (ufsi->i_lastfrag - 1) * uspi->s_fsize; | ||
492 | } | ||
493 | almost_end: | ||
407 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 494 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
408 | ufsi->i_lastfrag = DIRECT_FRAGMENT; | ||
409 | unlock_kernel(); | 495 | unlock_kernel(); |
410 | mark_inode_dirty(inode); | 496 | mark_inode_dirty(inode); |
411 | UFSD("EXIT\n"); | 497 | out: |
498 | UFSD("EXIT: err %d\n", err); | ||
499 | return err; | ||
412 | } | 500 | } |
501 | |||
502 | |||
503 | /* | ||
504 | * We don't define our `inode->i_op->truncate', and call it here, | ||
505 | * because of: | ||
506 | * - there is no way to know old size | ||
507 | * - there is no way inform user about error, if it happens in `truncate' | ||
508 | */ | ||
509 | static int ufs_setattr(struct dentry *dentry, struct iattr *attr) | ||
510 | { | ||
511 | struct inode *inode = dentry->d_inode; | ||
512 | unsigned int ia_valid = attr->ia_valid; | ||
513 | int error; | ||
514 | |||
515 | error = inode_change_ok(inode, attr); | ||
516 | if (error) | ||
517 | return error; | ||
518 | |||
519 | if (ia_valid & ATTR_SIZE && | ||
520 | attr->ia_size != i_size_read(inode)) { | ||
521 | loff_t old_i_size = inode->i_size; | ||
522 | error = vmtruncate(inode, attr->ia_size); | ||
523 | if (error) | ||
524 | return error; | ||
525 | error = ufs_truncate(inode, old_i_size); | ||
526 | if (error) | ||
527 | return error; | ||
528 | } | ||
529 | return inode_setattr(inode, attr); | ||
530 | } | ||
531 | |||
532 | struct inode_operations ufs_file_inode_operations = { | ||
533 | .setattr = ufs_setattr, | ||
534 | }; | ||
diff --git a/fs/ufs/util.c b/fs/ufs/util.c index a2f13f45708b..337cf2c46d10 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c | |||
@@ -233,3 +233,57 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev | |||
233 | else | 233 | else |
234 | ufsi->i_u1.i_data[0] = fs32; | 234 | ufsi->i_u1.i_data[0] = fs32; |
235 | } | 235 | } |
236 | |||
237 | /** | ||
238 | * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist | ||
239 | * read it from disk. | ||
240 | * @mapping: the address_space to search | ||
241 | * @index: the page index | ||
242 | * | ||
243 | * Locates the desired pagecache page, if not exist we'll read it, | ||
244 | * locks it, increments its reference | ||
245 | * count and returns its address. | ||
246 | * | ||
247 | */ | ||
248 | |||
249 | struct page *ufs_get_locked_page(struct address_space *mapping, | ||
250 | pgoff_t index) | ||
251 | { | ||
252 | struct page *page; | ||
253 | |||
254 | try_again: | ||
255 | page = find_lock_page(mapping, index); | ||
256 | if (!page) { | ||
257 | page = read_cache_page(mapping, index, | ||
258 | (filler_t*)mapping->a_ops->readpage, | ||
259 | NULL); | ||
260 | if (IS_ERR(page)) { | ||
261 | printk(KERN_ERR "ufs_change_blocknr: " | ||
262 | "read_cache_page error: ino %lu, index: %lu\n", | ||
263 | mapping->host->i_ino, index); | ||
264 | goto out; | ||
265 | } | ||
266 | |||
267 | lock_page(page); | ||
268 | |||
269 | if (!PageUptodate(page) || PageError(page)) { | ||
270 | unlock_page(page); | ||
271 | page_cache_release(page); | ||
272 | |||
273 | printk(KERN_ERR "ufs_change_blocknr: " | ||
274 | "can not read page: ino %lu, index: %lu\n", | ||
275 | mapping->host->i_ino, index); | ||
276 | |||
277 | page = ERR_PTR(-EIO); | ||
278 | goto out; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | if (unlikely(!page->mapping || !page_has_buffers(page))) { | ||
283 | unlock_page(page); | ||
284 | page_cache_release(page); | ||
285 | goto try_again;/*we really need these buffers*/ | ||
286 | } | ||
287 | out: | ||
288 | return page; | ||
289 | } | ||
diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 406981fff5e7..28fce6c239b5 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h | |||
@@ -251,6 +251,14 @@ extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struc | |||
251 | #define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size) | 251 | #define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size) |
252 | extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned); | 252 | extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned); |
253 | 253 | ||
254 | /* This functions works with cache pages*/ | ||
255 | extern struct page *ufs_get_locked_page(struct address_space *mapping, | ||
256 | pgoff_t index); | ||
257 | static inline void ufs_put_locked_page(struct page *page) | ||
258 | { | ||
259 | unlock_page(page); | ||
260 | page_cache_release(page); | ||
261 | } | ||
254 | 262 | ||
255 | 263 | ||
256 | /* | 264 | /* |
diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h new file mode 100644 index 000000000000..cb05bf69745a --- /dev/null +++ b/include/asm-generic/audit_change_attr.h | |||
@@ -0,0 +1,18 @@ | |||
1 | __NR_chmod, | ||
2 | __NR_fchmod, | ||
3 | __NR_chown, | ||
4 | __NR_fchown, | ||
5 | __NR_lchown, | ||
6 | __NR_setxattr, | ||
7 | __NR_lsetxattr, | ||
8 | __NR_fsetxattr, | ||
9 | __NR_removexattr, | ||
10 | __NR_lremovexattr, | ||
11 | __NR_fremovexattr, | ||
12 | __NR_fchownat, | ||
13 | __NR_fchmodat, | ||
14 | #ifdef __NR_chown32 | ||
15 | __NR_chown32, | ||
16 | __NR_fchown32, | ||
17 | __NR_lchown32, | ||
18 | #endif | ||
diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h new file mode 100644 index 000000000000..161a7a58fbab --- /dev/null +++ b/include/asm-generic/audit_dir_write.h | |||
@@ -0,0 +1,14 @@ | |||
1 | __NR_rename, | ||
2 | __NR_mkdir, | ||
3 | __NR_rmdir, | ||
4 | __NR_creat, | ||
5 | __NR_link, | ||
6 | __NR_unlink, | ||
7 | __NR_symlink, | ||
8 | __NR_mknod, | ||
9 | __NR_mkdirat, | ||
10 | __NR_mknodat, | ||
11 | __NR_unlinkat, | ||
12 | __NR_renameat, | ||
13 | __NR_linkat, | ||
14 | __NR_symlinkat, | ||
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 0b49f9e070f1..962cad7cfbbd 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h | |||
@@ -14,5 +14,6 @@ extern char _end[]; | |||
14 | extern char __per_cpu_start[], __per_cpu_end[]; | 14 | extern char __per_cpu_start[], __per_cpu_end[]; |
15 | extern char __kprobes_text_start[], __kprobes_text_end[]; | 15 | extern char __kprobes_text_start[], __kprobes_text_end[]; |
16 | extern char __initdata_begin[], __initdata_end[]; | 16 | extern char __initdata_begin[], __initdata_end[]; |
17 | extern char __start_rodata[], __end_rodata[]; | ||
17 | 18 | ||
18 | #endif /* _ASM_GENERIC_SECTIONS_H_ */ | 19 | #endif /* _ASM_GENERIC_SECTIONS_H_ */ |
diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h index c61bd1a17f37..96adbabec740 100644 --- a/include/asm-i386/alternative.h +++ b/include/asm-i386/alternative.h | |||
@@ -19,11 +19,19 @@ struct alt_instr { | |||
19 | extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); | 19 | extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); |
20 | 20 | ||
21 | struct module; | 21 | struct module; |
22 | #ifdef CONFIG_SMP | ||
22 | extern void alternatives_smp_module_add(struct module *mod, char *name, | 23 | extern void alternatives_smp_module_add(struct module *mod, char *name, |
23 | void *locks, void *locks_end, | 24 | void *locks, void *locks_end, |
24 | void *text, void *text_end); | 25 | void *text, void *text_end); |
25 | extern void alternatives_smp_module_del(struct module *mod); | 26 | extern void alternatives_smp_module_del(struct module *mod); |
26 | extern void alternatives_smp_switch(int smp); | 27 | extern void alternatives_smp_switch(int smp); |
28 | #else | ||
29 | static inline void alternatives_smp_module_add(struct module *mod, char *name, | ||
30 | void *locks, void *locks_end, | ||
31 | void *text, void *text_end) {} | ||
32 | static inline void alternatives_smp_module_del(struct module *mod) {} | ||
33 | static inline void alternatives_smp_switch(int smp) {} | ||
34 | #endif | ||
27 | 35 | ||
28 | #endif | 36 | #endif |
29 | 37 | ||
diff --git a/include/asm-um/kmap_types.h b/include/asm-um/kmap_types.h index 0b22ad776e76..6c03acdb4405 100644 --- a/include/asm-um/kmap_types.h +++ b/include/asm-um/kmap_types.h | |||
@@ -6,6 +6,24 @@ | |||
6 | #ifndef __UM_KMAP_TYPES_H | 6 | #ifndef __UM_KMAP_TYPES_H |
7 | #define __UM_KMAP_TYPES_H | 7 | #define __UM_KMAP_TYPES_H |
8 | 8 | ||
9 | #include "asm/arch/kmap_types.h" | 9 | /* No more #include "asm/arch/kmap_types.h" ! */ |
10 | |||
11 | enum km_type { | ||
12 | KM_BOUNCE_READ, | ||
13 | KM_SKB_SUNRPC_DATA, | ||
14 | KM_SKB_DATA_SOFTIRQ, | ||
15 | KM_USER0, | ||
16 | KM_USER1, | ||
17 | KM_UML_USERCOPY, /* UML specific, for copy_*_user - used in do_op_one_page */ | ||
18 | KM_BIO_SRC_IRQ, | ||
19 | KM_BIO_DST_IRQ, | ||
20 | KM_PTE0, | ||
21 | KM_PTE1, | ||
22 | KM_IRQ0, | ||
23 | KM_IRQ1, | ||
24 | KM_SOFTIRQ0, | ||
25 | KM_SOFTIRQ1, | ||
26 | KM_TYPE_NR | ||
27 | }; | ||
10 | 28 | ||
11 | #endif | 29 | #endif |
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h index 387c8f66af7d..aa67bfd1b3ce 100644 --- a/include/asm-x86_64/alternative.h +++ b/include/asm-x86_64/alternative.h | |||
@@ -17,11 +17,20 @@ struct alt_instr { | |||
17 | extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); | 17 | extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); |
18 | 18 | ||
19 | struct module; | 19 | struct module; |
20 | |||
21 | #ifdef CONFIG_SMP | ||
20 | extern void alternatives_smp_module_add(struct module *mod, char *name, | 22 | extern void alternatives_smp_module_add(struct module *mod, char *name, |
21 | void *locks, void *locks_end, | 23 | void *locks, void *locks_end, |
22 | void *text, void *text_end); | 24 | void *text, void *text_end); |
23 | extern void alternatives_smp_module_del(struct module *mod); | 25 | extern void alternatives_smp_module_del(struct module *mod); |
24 | extern void alternatives_smp_switch(int smp); | 26 | extern void alternatives_smp_switch(int smp); |
27 | #else | ||
28 | static inline void alternatives_smp_module_add(struct module *mod, char *name, | ||
29 | void *locks, void *locks_end, | ||
30 | void *text, void *text_end) {} | ||
31 | static inline void alternatives_smp_module_del(struct module *mod) {} | ||
32 | static inline void alternatives_smp_switch(int smp) {} | ||
33 | #endif | ||
25 | 34 | ||
26 | #endif | 35 | #endif |
27 | 36 | ||
diff --git a/include/linux/audit.h b/include/linux/audit.h index e051ff9c5b50..b27d7debc5a1 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -122,10 +122,17 @@ | |||
122 | /* Rule structure sizes -- if these change, different AUDIT_ADD and | 122 | /* Rule structure sizes -- if these change, different AUDIT_ADD and |
123 | * AUDIT_LIST commands must be implemented. */ | 123 | * AUDIT_LIST commands must be implemented. */ |
124 | #define AUDIT_MAX_FIELDS 64 | 124 | #define AUDIT_MAX_FIELDS 64 |
125 | #define AUDIT_MAX_KEY_LEN 32 | ||
125 | #define AUDIT_BITMASK_SIZE 64 | 126 | #define AUDIT_BITMASK_SIZE 64 |
126 | #define AUDIT_WORD(nr) ((__u32)((nr)/32)) | 127 | #define AUDIT_WORD(nr) ((__u32)((nr)/32)) |
127 | #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) | 128 | #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) |
128 | 129 | ||
130 | #define AUDIT_SYSCALL_CLASSES 16 | ||
131 | #define AUDIT_CLASS_DIR_WRITE 0 | ||
132 | #define AUDIT_CLASS_DIR_WRITE_32 1 | ||
133 | #define AUDIT_CLASS_CHATTR 2 | ||
134 | #define AUDIT_CLASS_CHATTR_32 3 | ||
135 | |||
129 | /* This bitmask is used to validate user input. It represents all bits that | 136 | /* This bitmask is used to validate user input. It represents all bits that |
130 | * are currently used in an audit field constant understood by the kernel. | 137 | * are currently used in an audit field constant understood by the kernel. |
131 | * If you are adding a new #define AUDIT_<whatever>, please ensure that | 138 | * If you are adding a new #define AUDIT_<whatever>, please ensure that |
@@ -150,12 +157,17 @@ | |||
150 | #define AUDIT_PERS 10 | 157 | #define AUDIT_PERS 10 |
151 | #define AUDIT_ARCH 11 | 158 | #define AUDIT_ARCH 11 |
152 | #define AUDIT_MSGTYPE 12 | 159 | #define AUDIT_MSGTYPE 12 |
153 | #define AUDIT_SE_USER 13 /* security label user */ | 160 | #define AUDIT_SUBJ_USER 13 /* security label user */ |
154 | #define AUDIT_SE_ROLE 14 /* security label role */ | 161 | #define AUDIT_SUBJ_ROLE 14 /* security label role */ |
155 | #define AUDIT_SE_TYPE 15 /* security label type */ | 162 | #define AUDIT_SUBJ_TYPE 15 /* security label type */ |
156 | #define AUDIT_SE_SEN 16 /* security label sensitivity label */ | 163 | #define AUDIT_SUBJ_SEN 16 /* security label sensitivity label */ |
157 | #define AUDIT_SE_CLR 17 /* security label clearance label */ | 164 | #define AUDIT_SUBJ_CLR 17 /* security label clearance label */ |
158 | #define AUDIT_PPID 18 | 165 | #define AUDIT_PPID 18 |
166 | #define AUDIT_OBJ_USER 19 | ||
167 | #define AUDIT_OBJ_ROLE 20 | ||
168 | #define AUDIT_OBJ_TYPE 21 | ||
169 | #define AUDIT_OBJ_LEV_LOW 22 | ||
170 | #define AUDIT_OBJ_LEV_HIGH 23 | ||
159 | 171 | ||
160 | /* These are ONLY useful when checking | 172 | /* These are ONLY useful when checking |
161 | * at syscall exit time (AUDIT_AT_EXIT). */ | 173 | * at syscall exit time (AUDIT_AT_EXIT). */ |
@@ -171,6 +183,8 @@ | |||
171 | #define AUDIT_ARG2 (AUDIT_ARG0+2) | 183 | #define AUDIT_ARG2 (AUDIT_ARG0+2) |
172 | #define AUDIT_ARG3 (AUDIT_ARG0+3) | 184 | #define AUDIT_ARG3 (AUDIT_ARG0+3) |
173 | 185 | ||
186 | #define AUDIT_FILTERKEY 210 | ||
187 | |||
174 | #define AUDIT_NEGATE 0x80000000 | 188 | #define AUDIT_NEGATE 0x80000000 |
175 | 189 | ||
176 | /* These are the supported operators. | 190 | /* These are the supported operators. |
@@ -299,6 +313,7 @@ struct mqstat; | |||
299 | #define AUDITSC_SUCCESS 1 | 313 | #define AUDITSC_SUCCESS 1 |
300 | #define AUDITSC_FAILURE 2 | 314 | #define AUDITSC_FAILURE 2 |
301 | #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) | 315 | #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) |
316 | extern int __init audit_register_class(int class, unsigned *list); | ||
302 | #ifdef CONFIG_AUDITSYSCALL | 317 | #ifdef CONFIG_AUDITSYSCALL |
303 | /* These are defined in auditsc.c */ | 318 | /* These are defined in auditsc.c */ |
304 | /* Public API */ | 319 | /* Public API */ |
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index a3caf6866bae..44a11f1ccaf2 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -87,9 +87,9 @@ int cpu_down(unsigned int cpu); | |||
87 | #define lock_cpu_hotplug() do { } while (0) | 87 | #define lock_cpu_hotplug() do { } while (0) |
88 | #define unlock_cpu_hotplug() do { } while (0) | 88 | #define unlock_cpu_hotplug() do { } while (0) |
89 | #define lock_cpu_hotplug_interruptible() 0 | 89 | #define lock_cpu_hotplug_interruptible() 0 |
90 | #define hotcpu_notifier(fn, pri) | 90 | #define hotcpu_notifier(fn, pri) do { } while (0) |
91 | #define register_hotcpu_notifier(nb) | 91 | #define register_hotcpu_notifier(nb) do { } while (0) |
92 | #define unregister_hotcpu_notifier(nb) | 92 | #define unregister_hotcpu_notifier(nb) do { } while (0) |
93 | 93 | ||
94 | /* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */ | 94 | /* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */ |
95 | static inline int cpu_is_offline(int cpu) { return 0; } | 95 | static inline int cpu_is_offline(int cpu) { return 0; } |
diff --git a/include/linux/err.h b/include/linux/err.h index ff71d2af5da3..cd3b367f7445 100644 --- a/include/linux/err.h +++ b/include/linux/err.h | |||
@@ -13,7 +13,9 @@ | |||
13 | * This should be a per-architecture thing, to allow different | 13 | * This should be a per-architecture thing, to allow different |
14 | * error and pointer decisions. | 14 | * error and pointer decisions. |
15 | */ | 15 | */ |
16 | #define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L) | 16 | #define MAX_ERRNO 4095 |
17 | |||
18 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) | ||
17 | 19 | ||
18 | static inline void *ERR_PTR(long error) | 20 | static inline void *ERR_PTR(long error) |
19 | { | 21 | { |
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index e39b7cc43390..fc62887c5206 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h | |||
@@ -993,7 +993,7 @@ extern void ufs_panic (struct super_block *, const char *, const char *, ...) __ | |||
993 | extern struct inode_operations ufs_fast_symlink_inode_operations; | 993 | extern struct inode_operations ufs_fast_symlink_inode_operations; |
994 | 994 | ||
995 | /* truncate.c */ | 995 | /* truncate.c */ |
996 | extern void ufs_truncate (struct inode *); | 996 | extern int ufs_truncate (struct inode *, loff_t); |
997 | 997 | ||
998 | static inline struct ufs_sb_info *UFS_SB(struct super_block *sb) | 998 | static inline struct ufs_sb_info *UFS_SB(struct super_block *sb) |
999 | { | 999 | { |
diff --git a/kernel/audit.h b/kernel/audit.h index 8323e4132a33..6aa33b848cf2 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -81,6 +81,7 @@ struct audit_krule { | |||
81 | u32 mask[AUDIT_BITMASK_SIZE]; | 81 | u32 mask[AUDIT_BITMASK_SIZE]; |
82 | u32 buflen; /* for data alloc on list rules */ | 82 | u32 buflen; /* for data alloc on list rules */ |
83 | u32 field_count; | 83 | u32 field_count; |
84 | char *filterkey; /* ties events to rules */ | ||
84 | struct audit_field *fields; | 85 | struct audit_field *fields; |
85 | struct audit_field *inode_f; /* quick access to an inode field */ | 86 | struct audit_field *inode_f; /* quick access to an inode field */ |
86 | struct audit_watch *watch; /* associated watch */ | 87 | struct audit_watch *watch; /* associated watch */ |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 4c99d2c586ed..5b4e16276ca0 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -141,6 +141,7 @@ static inline void audit_free_rule(struct audit_entry *e) | |||
141 | selinux_audit_rule_free(f->se_rule); | 141 | selinux_audit_rule_free(f->se_rule); |
142 | } | 142 | } |
143 | kfree(e->rule.fields); | 143 | kfree(e->rule.fields); |
144 | kfree(e->rule.filterkey); | ||
144 | kfree(e); | 145 | kfree(e); |
145 | } | 146 | } |
146 | 147 | ||
@@ -278,6 +279,29 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len, | |||
278 | return 0; | 279 | return 0; |
279 | } | 280 | } |
280 | 281 | ||
282 | static __u32 *classes[AUDIT_SYSCALL_CLASSES]; | ||
283 | |||
284 | int __init audit_register_class(int class, unsigned *list) | ||
285 | { | ||
286 | __u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL); | ||
287 | if (!p) | ||
288 | return -ENOMEM; | ||
289 | while (*list != ~0U) { | ||
290 | unsigned n = *list++; | ||
291 | if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) { | ||
292 | kfree(p); | ||
293 | return -EINVAL; | ||
294 | } | ||
295 | p[AUDIT_WORD(n)] |= AUDIT_BIT(n); | ||
296 | } | ||
297 | if (class >= AUDIT_SYSCALL_CLASSES || classes[class]) { | ||
298 | kfree(p); | ||
299 | return -EINVAL; | ||
300 | } | ||
301 | classes[class] = p; | ||
302 | return 0; | ||
303 | } | ||
304 | |||
281 | /* Common user-space to kernel rule translation. */ | 305 | /* Common user-space to kernel rule translation. */ |
282 | static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) | 306 | static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) |
283 | { | 307 | { |
@@ -321,6 +345,22 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) | |||
321 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) | 345 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) |
322 | entry->rule.mask[i] = rule->mask[i]; | 346 | entry->rule.mask[i] = rule->mask[i]; |
323 | 347 | ||
348 | for (i = 0; i < AUDIT_SYSCALL_CLASSES; i++) { | ||
349 | int bit = AUDIT_BITMASK_SIZE * 32 - i - 1; | ||
350 | __u32 *p = &entry->rule.mask[AUDIT_WORD(bit)]; | ||
351 | __u32 *class; | ||
352 | |||
353 | if (!(*p & AUDIT_BIT(bit))) | ||
354 | continue; | ||
355 | *p &= ~AUDIT_BIT(bit); | ||
356 | class = classes[i]; | ||
357 | if (class) { | ||
358 | int j; | ||
359 | for (j = 0; j < AUDIT_BITMASK_SIZE; j++) | ||
360 | entry->rule.mask[j] |= class[j]; | ||
361 | } | ||
362 | } | ||
363 | |||
324 | return entry; | 364 | return entry; |
325 | 365 | ||
326 | exit_err: | 366 | exit_err: |
@@ -469,11 +509,16 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
469 | case AUDIT_ARG2: | 509 | case AUDIT_ARG2: |
470 | case AUDIT_ARG3: | 510 | case AUDIT_ARG3: |
471 | break; | 511 | break; |
472 | case AUDIT_SE_USER: | 512 | case AUDIT_SUBJ_USER: |
473 | case AUDIT_SE_ROLE: | 513 | case AUDIT_SUBJ_ROLE: |
474 | case AUDIT_SE_TYPE: | 514 | case AUDIT_SUBJ_TYPE: |
475 | case AUDIT_SE_SEN: | 515 | case AUDIT_SUBJ_SEN: |
476 | case AUDIT_SE_CLR: | 516 | case AUDIT_SUBJ_CLR: |
517 | case AUDIT_OBJ_USER: | ||
518 | case AUDIT_OBJ_ROLE: | ||
519 | case AUDIT_OBJ_TYPE: | ||
520 | case AUDIT_OBJ_LEV_LOW: | ||
521 | case AUDIT_OBJ_LEV_HIGH: | ||
477 | str = audit_unpack_string(&bufp, &remain, f->val); | 522 | str = audit_unpack_string(&bufp, &remain, f->val); |
478 | if (IS_ERR(str)) | 523 | if (IS_ERR(str)) |
479 | goto exit_free; | 524 | goto exit_free; |
@@ -511,6 +556,16 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
511 | if (err) | 556 | if (err) |
512 | goto exit_free; | 557 | goto exit_free; |
513 | break; | 558 | break; |
559 | case AUDIT_FILTERKEY: | ||
560 | err = -EINVAL; | ||
561 | if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN) | ||
562 | goto exit_free; | ||
563 | str = audit_unpack_string(&bufp, &remain, f->val); | ||
564 | if (IS_ERR(str)) | ||
565 | goto exit_free; | ||
566 | entry->rule.buflen += f->val; | ||
567 | entry->rule.filterkey = str; | ||
568 | break; | ||
514 | default: | 569 | default: |
515 | goto exit_free; | 570 | goto exit_free; |
516 | } | 571 | } |
@@ -600,11 +655,16 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | |||
600 | data->fields[i] = f->type; | 655 | data->fields[i] = f->type; |
601 | data->fieldflags[i] = f->op; | 656 | data->fieldflags[i] = f->op; |
602 | switch(f->type) { | 657 | switch(f->type) { |
603 | case AUDIT_SE_USER: | 658 | case AUDIT_SUBJ_USER: |
604 | case AUDIT_SE_ROLE: | 659 | case AUDIT_SUBJ_ROLE: |
605 | case AUDIT_SE_TYPE: | 660 | case AUDIT_SUBJ_TYPE: |
606 | case AUDIT_SE_SEN: | 661 | case AUDIT_SUBJ_SEN: |
607 | case AUDIT_SE_CLR: | 662 | case AUDIT_SUBJ_CLR: |
663 | case AUDIT_OBJ_USER: | ||
664 | case AUDIT_OBJ_ROLE: | ||
665 | case AUDIT_OBJ_TYPE: | ||
666 | case AUDIT_OBJ_LEV_LOW: | ||
667 | case AUDIT_OBJ_LEV_HIGH: | ||
608 | data->buflen += data->values[i] = | 668 | data->buflen += data->values[i] = |
609 | audit_pack_string(&bufp, f->se_str); | 669 | audit_pack_string(&bufp, f->se_str); |
610 | break; | 670 | break; |
@@ -612,6 +672,10 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | |||
612 | data->buflen += data->values[i] = | 672 | data->buflen += data->values[i] = |
613 | audit_pack_string(&bufp, krule->watch->path); | 673 | audit_pack_string(&bufp, krule->watch->path); |
614 | break; | 674 | break; |
675 | case AUDIT_FILTERKEY: | ||
676 | data->buflen += data->values[i] = | ||
677 | audit_pack_string(&bufp, krule->filterkey); | ||
678 | break; | ||
615 | default: | 679 | default: |
616 | data->values[i] = f->val; | 680 | data->values[i] = f->val; |
617 | } | 681 | } |
@@ -639,11 +703,16 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
639 | return 1; | 703 | return 1; |
640 | 704 | ||
641 | switch(a->fields[i].type) { | 705 | switch(a->fields[i].type) { |
642 | case AUDIT_SE_USER: | 706 | case AUDIT_SUBJ_USER: |
643 | case AUDIT_SE_ROLE: | 707 | case AUDIT_SUBJ_ROLE: |
644 | case AUDIT_SE_TYPE: | 708 | case AUDIT_SUBJ_TYPE: |
645 | case AUDIT_SE_SEN: | 709 | case AUDIT_SUBJ_SEN: |
646 | case AUDIT_SE_CLR: | 710 | case AUDIT_SUBJ_CLR: |
711 | case AUDIT_OBJ_USER: | ||
712 | case AUDIT_OBJ_ROLE: | ||
713 | case AUDIT_OBJ_TYPE: | ||
714 | case AUDIT_OBJ_LEV_LOW: | ||
715 | case AUDIT_OBJ_LEV_HIGH: | ||
647 | if (strcmp(a->fields[i].se_str, b->fields[i].se_str)) | 716 | if (strcmp(a->fields[i].se_str, b->fields[i].se_str)) |
648 | return 1; | 717 | return 1; |
649 | break; | 718 | break; |
@@ -651,6 +720,11 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
651 | if (strcmp(a->watch->path, b->watch->path)) | 720 | if (strcmp(a->watch->path, b->watch->path)) |
652 | return 1; | 721 | return 1; |
653 | break; | 722 | break; |
723 | case AUDIT_FILTERKEY: | ||
724 | /* both filterkeys exist based on above type compare */ | ||
725 | if (strcmp(a->filterkey, b->filterkey)) | ||
726 | return 1; | ||
727 | break; | ||
654 | default: | 728 | default: |
655 | if (a->fields[i].val != b->fields[i].val) | 729 | if (a->fields[i].val != b->fields[i].val) |
656 | return 1; | 730 | return 1; |
@@ -730,6 +804,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, | |||
730 | u32 fcount = old->field_count; | 804 | u32 fcount = old->field_count; |
731 | struct audit_entry *entry; | 805 | struct audit_entry *entry; |
732 | struct audit_krule *new; | 806 | struct audit_krule *new; |
807 | char *fk; | ||
733 | int i, err = 0; | 808 | int i, err = 0; |
734 | 809 | ||
735 | entry = audit_init_entry(fcount); | 810 | entry = audit_init_entry(fcount); |
@@ -753,13 +828,25 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, | |||
753 | * the originals will all be freed when the old rule is freed. */ | 828 | * the originals will all be freed when the old rule is freed. */ |
754 | for (i = 0; i < fcount; i++) { | 829 | for (i = 0; i < fcount; i++) { |
755 | switch (new->fields[i].type) { | 830 | switch (new->fields[i].type) { |
756 | case AUDIT_SE_USER: | 831 | case AUDIT_SUBJ_USER: |
757 | case AUDIT_SE_ROLE: | 832 | case AUDIT_SUBJ_ROLE: |
758 | case AUDIT_SE_TYPE: | 833 | case AUDIT_SUBJ_TYPE: |
759 | case AUDIT_SE_SEN: | 834 | case AUDIT_SUBJ_SEN: |
760 | case AUDIT_SE_CLR: | 835 | case AUDIT_SUBJ_CLR: |
836 | case AUDIT_OBJ_USER: | ||
837 | case AUDIT_OBJ_ROLE: | ||
838 | case AUDIT_OBJ_TYPE: | ||
839 | case AUDIT_OBJ_LEV_LOW: | ||
840 | case AUDIT_OBJ_LEV_HIGH: | ||
761 | err = audit_dupe_selinux_field(&new->fields[i], | 841 | err = audit_dupe_selinux_field(&new->fields[i], |
762 | &old->fields[i]); | 842 | &old->fields[i]); |
843 | break; | ||
844 | case AUDIT_FILTERKEY: | ||
845 | fk = kstrdup(old->filterkey, GFP_KERNEL); | ||
846 | if (unlikely(!fk)) | ||
847 | err = -ENOMEM; | ||
848 | else | ||
849 | new->filterkey = fk; | ||
763 | } | 850 | } |
764 | if (err) { | 851 | if (err) { |
765 | audit_free_rule(entry); | 852 | audit_free_rule(entry); |
@@ -1245,6 +1332,34 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | |||
1245 | skb_queue_tail(q, skb); | 1332 | skb_queue_tail(q, skb); |
1246 | } | 1333 | } |
1247 | 1334 | ||
1335 | /* Log rule additions and removals */ | ||
1336 | static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, | ||
1337 | struct audit_krule *rule, int res) | ||
1338 | { | ||
1339 | struct audit_buffer *ab; | ||
1340 | |||
1341 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | ||
1342 | if (!ab) | ||
1343 | return; | ||
1344 | audit_log_format(ab, "auid=%u", loginuid); | ||
1345 | if (sid) { | ||
1346 | char *ctx = NULL; | ||
1347 | u32 len; | ||
1348 | if (selinux_ctxid_to_string(sid, &ctx, &len)) | ||
1349 | audit_log_format(ab, " ssid=%u", sid); | ||
1350 | else | ||
1351 | audit_log_format(ab, " subj=%s", ctx); | ||
1352 | kfree(ctx); | ||
1353 | } | ||
1354 | audit_log_format(ab, " %s rule key=", action); | ||
1355 | if (rule->filterkey) | ||
1356 | audit_log_untrustedstring(ab, rule->filterkey); | ||
1357 | else | ||
1358 | audit_log_format(ab, "(null)"); | ||
1359 | audit_log_format(ab, " list=%d res=%d", rule->listnr, res); | ||
1360 | audit_log_end(ab); | ||
1361 | } | ||
1362 | |||
1248 | /** | 1363 | /** |
1249 | * audit_receive_filter - apply all rules to the specified message type | 1364 | * audit_receive_filter - apply all rules to the specified message type |
1250 | * @type: audit message type | 1365 | * @type: audit message type |
@@ -1304,24 +1419,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
1304 | 1419 | ||
1305 | err = audit_add_rule(entry, | 1420 | err = audit_add_rule(entry, |
1306 | &audit_filter_list[entry->rule.listnr]); | 1421 | &audit_filter_list[entry->rule.listnr]); |
1307 | 1422 | audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err); | |
1308 | if (sid) { | ||
1309 | char *ctx = NULL; | ||
1310 | u32 len; | ||
1311 | if (selinux_ctxid_to_string(sid, &ctx, &len)) { | ||
1312 | /* Maybe call audit_panic? */ | ||
1313 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
1314 | "auid=%u ssid=%u add rule to list=%d res=%d", | ||
1315 | loginuid, sid, entry->rule.listnr, !err); | ||
1316 | } else | ||
1317 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
1318 | "auid=%u subj=%s add rule to list=%d res=%d", | ||
1319 | loginuid, ctx, entry->rule.listnr, !err); | ||
1320 | kfree(ctx); | ||
1321 | } else | ||
1322 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
1323 | "auid=%u add rule to list=%d res=%d", | ||
1324 | loginuid, entry->rule.listnr, !err); | ||
1325 | 1423 | ||
1326 | if (err) | 1424 | if (err) |
1327 | audit_free_rule(entry); | 1425 | audit_free_rule(entry); |
@@ -1337,24 +1435,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
1337 | 1435 | ||
1338 | err = audit_del_rule(entry, | 1436 | err = audit_del_rule(entry, |
1339 | &audit_filter_list[entry->rule.listnr]); | 1437 | &audit_filter_list[entry->rule.listnr]); |
1340 | 1438 | audit_log_rule_change(loginuid, sid, "remove", &entry->rule, | |
1341 | if (sid) { | 1439 | !err); |
1342 | char *ctx = NULL; | ||
1343 | u32 len; | ||
1344 | if (selinux_ctxid_to_string(sid, &ctx, &len)) { | ||
1345 | /* Maybe call audit_panic? */ | ||
1346 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
1347 | "auid=%u ssid=%u remove rule from list=%d res=%d", | ||
1348 | loginuid, sid, entry->rule.listnr, !err); | ||
1349 | } else | ||
1350 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
1351 | "auid=%u subj=%s remove rule from list=%d res=%d", | ||
1352 | loginuid, ctx, entry->rule.listnr, !err); | ||
1353 | kfree(ctx); | ||
1354 | } else | ||
1355 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | ||
1356 | "auid=%u remove rule from list=%d res=%d", | ||
1357 | loginuid, entry->rule.listnr, !err); | ||
1358 | 1440 | ||
1359 | audit_free_rule(entry); | 1441 | audit_free_rule(entry); |
1360 | break; | 1442 | break; |
@@ -1514,11 +1596,16 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule) | |||
1514 | for (i = 0; i < rule->field_count; i++) { | 1596 | for (i = 0; i < rule->field_count; i++) { |
1515 | struct audit_field *f = &rule->fields[i]; | 1597 | struct audit_field *f = &rule->fields[i]; |
1516 | switch (f->type) { | 1598 | switch (f->type) { |
1517 | case AUDIT_SE_USER: | 1599 | case AUDIT_SUBJ_USER: |
1518 | case AUDIT_SE_ROLE: | 1600 | case AUDIT_SUBJ_ROLE: |
1519 | case AUDIT_SE_TYPE: | 1601 | case AUDIT_SUBJ_TYPE: |
1520 | case AUDIT_SE_SEN: | 1602 | case AUDIT_SUBJ_SEN: |
1521 | case AUDIT_SE_CLR: | 1603 | case AUDIT_SUBJ_CLR: |
1604 | case AUDIT_OBJ_USER: | ||
1605 | case AUDIT_OBJ_ROLE: | ||
1606 | case AUDIT_OBJ_TYPE: | ||
1607 | case AUDIT_OBJ_LEV_LOW: | ||
1608 | case AUDIT_OBJ_LEV_HIGH: | ||
1522 | return 1; | 1609 | return 1; |
1523 | } | 1610 | } |
1524 | } | 1611 | } |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index dc5e3f01efe7..ae40ac8c39e7 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -186,6 +186,7 @@ struct audit_context { | |||
186 | int auditable; /* 1 if record should be written */ | 186 | int auditable; /* 1 if record should be written */ |
187 | int name_count; | 187 | int name_count; |
188 | struct audit_names names[AUDIT_NAMES]; | 188 | struct audit_names names[AUDIT_NAMES]; |
189 | char * filterkey; /* key for rule that triggered record */ | ||
189 | struct dentry * pwd; | 190 | struct dentry * pwd; |
190 | struct vfsmount * pwdmnt; | 191 | struct vfsmount * pwdmnt; |
191 | struct audit_context *previous; /* For nested syscalls */ | 192 | struct audit_context *previous; /* For nested syscalls */ |
@@ -320,11 +321,11 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
320 | if (ctx) | 321 | if (ctx) |
321 | result = audit_comparator(ctx->loginuid, f->op, f->val); | 322 | result = audit_comparator(ctx->loginuid, f->op, f->val); |
322 | break; | 323 | break; |
323 | case AUDIT_SE_USER: | 324 | case AUDIT_SUBJ_USER: |
324 | case AUDIT_SE_ROLE: | 325 | case AUDIT_SUBJ_ROLE: |
325 | case AUDIT_SE_TYPE: | 326 | case AUDIT_SUBJ_TYPE: |
326 | case AUDIT_SE_SEN: | 327 | case AUDIT_SUBJ_SEN: |
327 | case AUDIT_SE_CLR: | 328 | case AUDIT_SUBJ_CLR: |
328 | /* NOTE: this may return negative values indicating | 329 | /* NOTE: this may return negative values indicating |
329 | a temporary error. We simply treat this as a | 330 | a temporary error. We simply treat this as a |
330 | match for now to avoid losing information that | 331 | match for now to avoid losing information that |
@@ -341,6 +342,46 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
341 | ctx); | 342 | ctx); |
342 | } | 343 | } |
343 | break; | 344 | break; |
345 | case AUDIT_OBJ_USER: | ||
346 | case AUDIT_OBJ_ROLE: | ||
347 | case AUDIT_OBJ_TYPE: | ||
348 | case AUDIT_OBJ_LEV_LOW: | ||
349 | case AUDIT_OBJ_LEV_HIGH: | ||
350 | /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR | ||
351 | also applies here */ | ||
352 | if (f->se_rule) { | ||
353 | /* Find files that match */ | ||
354 | if (name) { | ||
355 | result = selinux_audit_rule_match( | ||
356 | name->osid, f->type, f->op, | ||
357 | f->se_rule, ctx); | ||
358 | } else if (ctx) { | ||
359 | for (j = 0; j < ctx->name_count; j++) { | ||
360 | if (selinux_audit_rule_match( | ||
361 | ctx->names[j].osid, | ||
362 | f->type, f->op, | ||
363 | f->se_rule, ctx)) { | ||
364 | ++result; | ||
365 | break; | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | /* Find ipc objects that match */ | ||
370 | if (ctx) { | ||
371 | struct audit_aux_data *aux; | ||
372 | for (aux = ctx->aux; aux; | ||
373 | aux = aux->next) { | ||
374 | if (aux->type == AUDIT_IPC) { | ||
375 | struct audit_aux_data_ipcctl *axi = (void *)aux; | ||
376 | if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) { | ||
377 | ++result; | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | break; | ||
344 | case AUDIT_ARG0: | 385 | case AUDIT_ARG0: |
345 | case AUDIT_ARG1: | 386 | case AUDIT_ARG1: |
346 | case AUDIT_ARG2: | 387 | case AUDIT_ARG2: |
@@ -348,11 +389,17 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
348 | if (ctx) | 389 | if (ctx) |
349 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); | 390 | result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); |
350 | break; | 391 | break; |
392 | case AUDIT_FILTERKEY: | ||
393 | /* ignore this field for filtering */ | ||
394 | result = 1; | ||
395 | break; | ||
351 | } | 396 | } |
352 | 397 | ||
353 | if (!result) | 398 | if (!result) |
354 | return 0; | 399 | return 0; |
355 | } | 400 | } |
401 | if (rule->filterkey) | ||
402 | ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); | ||
356 | switch (rule->action) { | 403 | switch (rule->action) { |
357 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; | 404 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; |
358 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; | 405 | case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; |
@@ -627,6 +674,7 @@ static inline void audit_free_context(struct audit_context *context) | |||
627 | } | 674 | } |
628 | audit_free_names(context); | 675 | audit_free_names(context); |
629 | audit_free_aux(context); | 676 | audit_free_aux(context); |
677 | kfree(context->filterkey); | ||
630 | kfree(context); | 678 | kfree(context); |
631 | context = previous; | 679 | context = previous; |
632 | } while (context); | 680 | } while (context); |
@@ -735,6 +783,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
735 | context->euid, context->suid, context->fsuid, | 783 | context->euid, context->suid, context->fsuid, |
736 | context->egid, context->sgid, context->fsgid, tty); | 784 | context->egid, context->sgid, context->fsgid, tty); |
737 | audit_log_task_info(ab, tsk); | 785 | audit_log_task_info(ab, tsk); |
786 | if (context->filterkey) { | ||
787 | audit_log_format(ab, " key="); | ||
788 | audit_log_untrustedstring(ab, context->filterkey); | ||
789 | } else | ||
790 | audit_log_format(ab, " key=(null)"); | ||
738 | audit_log_end(ab); | 791 | audit_log_end(ab); |
739 | 792 | ||
740 | for (aux = context->aux; aux; aux = aux->next) { | 793 | for (aux = context->aux; aux; aux = aux->next) { |
@@ -1060,6 +1113,8 @@ void audit_syscall_exit(int valid, long return_code) | |||
1060 | } else { | 1113 | } else { |
1061 | audit_free_names(context); | 1114 | audit_free_names(context); |
1062 | audit_free_aux(context); | 1115 | audit_free_aux(context); |
1116 | kfree(context->filterkey); | ||
1117 | context->filterkey = NULL; | ||
1063 | tsk->audit_context = context; | 1118 | tsk->audit_context = context; |
1064 | } | 1119 | } |
1065 | } | 1120 | } |
diff --git a/kernel/futex.c b/kernel/futex.c index 6c91f938005d..15caf93e4a43 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -630,8 +630,10 @@ static int futex_wake(u32 __user *uaddr, int nr_wake) | |||
630 | 630 | ||
631 | list_for_each_entry_safe(this, next, head, list) { | 631 | list_for_each_entry_safe(this, next, head, list) { |
632 | if (match_futex (&this->key, &key)) { | 632 | if (match_futex (&this->key, &key)) { |
633 | if (this->pi_state) | 633 | if (this->pi_state) { |
634 | return -EINVAL; | 634 | ret = -EINVAL; |
635 | break; | ||
636 | } | ||
635 | wake_futex(this); | 637 | wake_futex(this); |
636 | if (++ret >= nr_wake) | 638 | if (++ret >= nr_wake) |
637 | break; | 639 | break; |
@@ -1208,7 +1210,7 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, | |||
1208 | } | 1210 | } |
1209 | 1211 | ||
1210 | down_read(&curr->mm->mmap_sem); | 1212 | down_read(&curr->mm->mmap_sem); |
1211 | hb = queue_lock(&q, -1, NULL); | 1213 | spin_lock(q.lock_ptr); |
1212 | 1214 | ||
1213 | /* | 1215 | /* |
1214 | * Got the lock. We might not be the anticipated owner if we | 1216 | * Got the lock. We might not be the anticipated owner if we |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index b7117e81ac56..fcce5181e453 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -114,7 +114,7 @@ void enable_irq(unsigned int irq) | |||
114 | spin_lock_irqsave(&desc->lock, flags); | 114 | spin_lock_irqsave(&desc->lock, flags); |
115 | switch (desc->depth) { | 115 | switch (desc->depth) { |
116 | case 0: | 116 | case 0: |
117 | printk(KERN_WARNING "Unablanced enable_irq(%d)\n", irq); | 117 | printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); |
118 | WARN_ON(1); | 118 | WARN_ON(1); |
119 | break; | 119 | break; |
120 | case 1: { | 120 | case 1: { |
@@ -236,7 +236,8 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
236 | 236 | ||
237 | #if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) | 237 | #if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) |
238 | /* All handlers must agree on per-cpuness */ | 238 | /* All handlers must agree on per-cpuness */ |
239 | if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU)) | 239 | if ((old->flags & SA_PERCPU_IRQ) != |
240 | (new->flags & SA_PERCPU_IRQ)) | ||
240 | goto mismatch; | 241 | goto mismatch; |
241 | #endif | 242 | #endif |
242 | 243 | ||
@@ -266,9 +267,10 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
266 | * SA_TRIGGER_* but the PIC does not support | 267 | * SA_TRIGGER_* but the PIC does not support |
267 | * multiple flow-types? | 268 | * multiple flow-types? |
268 | */ | 269 | */ |
269 | printk(KERN_WARNING "setup_irq(%d) SA_TRIGGER" | 270 | printk(KERN_WARNING "No SA_TRIGGER set_type " |
270 | "set. No set_type function available\n", | 271 | "function for IRQ %d (%s)\n", irq, |
271 | irq); | 272 | desc->chip ? desc->chip->name : |
273 | "unknown"); | ||
272 | } else | 274 | } else |
273 | compat_irq_chip_set_default_handler(desc); | 275 | compat_irq_chip_set_default_handler(desc); |
274 | 276 | ||
@@ -298,7 +300,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
298 | mismatch: | 300 | mismatch: |
299 | spin_unlock_irqrestore(&desc->lock, flags); | 301 | spin_unlock_irqrestore(&desc->lock, flags); |
300 | if (!(new->flags & SA_PROBEIRQ)) { | 302 | if (!(new->flags & SA_PROBEIRQ)) { |
301 | printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__); | 303 | printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq); |
302 | dump_stack(); | 304 | dump_stack(); |
303 | } | 305 | } |
304 | return -EBUSY; | 306 | return -EBUSY; |
@@ -365,7 +367,7 @@ void free_irq(unsigned int irq, void *dev_id) | |||
365 | kfree(action); | 367 | kfree(action); |
366 | return; | 368 | return; |
367 | } | 369 | } |
368 | printk(KERN_ERR "Trying to free free IRQ%d\n", irq); | 370 | printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq); |
369 | spin_unlock_irqrestore(&desc->lock, flags); | 371 | spin_unlock_irqrestore(&desc->lock, flags); |
370 | return; | 372 | return; |
371 | } | 373 | } |
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index b0d067be7390..2180c88cfe89 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include | |||
@@ -13,6 +13,10 @@ space := $(empty) $(empty) | |||
13 | depfile = $(subst $(comma),_,$(@D)/.$(@F).d) | 13 | depfile = $(subst $(comma),_,$(@D)/.$(@F).d) |
14 | 14 | ||
15 | ### | 15 | ### |
16 | # filename of target with directory and extension stripped | ||
17 | basetarget = $(basename $(notdir $@)) | ||
18 | |||
19 | ### | ||
16 | # Escape single quote for use in echo statements | 20 | # Escape single quote for use in echo statements |
17 | escsq = $(subst $(squote),'\$(squote)',$1) | 21 | escsq = $(subst $(squote),'\$(squote)',$1) |
18 | 22 | ||
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 02a7eea5fdbc..3cb445cc7432 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build | |||
@@ -117,7 +117,7 @@ $(real-objs-m:.o=.lst): quiet_modtag := [M] | |||
117 | $(obj-m) : quiet_modtag := [M] | 117 | $(obj-m) : quiet_modtag := [M] |
118 | 118 | ||
119 | # Default for not multi-part modules | 119 | # Default for not multi-part modules |
120 | modname = $(*F) | 120 | modname = $(basetarget) |
121 | 121 | ||
122 | $(multi-objs-m) : modname = $(modname-multi) | 122 | $(multi-objs-m) : modname = $(modname-multi) |
123 | $(multi-objs-m:.o=.i) : modname = $(modname-multi) | 123 | $(multi-objs-m:.o=.i) : modname = $(modname-multi) |
diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 2b066d12af2c..18ecd4d5df7f 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host | |||
@@ -80,8 +80,10 @@ obj-dirs += $(host-objdirs) | |||
80 | ##### | 80 | ##### |
81 | # Handle options to gcc. Support building with separate output directory | 81 | # Handle options to gcc. Support building with separate output directory |
82 | 82 | ||
83 | _hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS_$(*F).o) | 83 | _hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \ |
84 | _hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o) | 84 | $(HOSTCFLAGS_$(basetarget).o) |
85 | _hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \ | ||
86 | $(HOSTCXXFLAGS_$(basetarget).o) | ||
85 | 87 | ||
86 | ifeq ($(KBUILD_SRC),) | 88 | ifeq ($(KBUILD_SRC),) |
87 | __hostc_flags = $(_hostc_flags) | 89 | __hostc_flags = $(_hostc_flags) |
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 2cb4935e85d1..fc498fee68ed 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib | |||
@@ -82,12 +82,12 @@ obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) | |||
82 | # than one module. In that case KBUILD_MODNAME will be set to foo_bar, | 82 | # than one module. In that case KBUILD_MODNAME will be set to foo_bar, |
83 | # where foo and bar are the name of the modules. | 83 | # where foo and bar are the name of the modules. |
84 | name-fix = $(subst $(comma),_,$(subst -,_,$1)) | 84 | name-fix = $(subst $(comma),_,$(subst -,_,$1)) |
85 | basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(*F)))" | 85 | basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" |
86 | modname_flags = $(if $(filter 1,$(words $(modname))),\ | 86 | modname_flags = $(if $(filter 1,$(words $(modname))),\ |
87 | -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") | 87 | -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") |
88 | 88 | ||
89 | _c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) | 89 | _c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(basetarget).o) |
90 | _a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o) | 90 | _a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o) |
91 | _cpp_flags = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F)) | 91 | _cpp_flags = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F)) |
92 | 92 | ||
93 | # If building the kernel in a separate objtree expand all occurrences | 93 | # If building the kernel in a separate objtree expand all occurrences |
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 576cce5e387f..a49550205dcc 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost | |||
@@ -72,7 +72,7 @@ $(modules:.ko=.mod.c): __modpost ; | |||
72 | # Step 5), compile all *.mod.c files | 72 | # Step 5), compile all *.mod.c files |
73 | 73 | ||
74 | # modname is set to make c_flags define KBUILD_MODNAME | 74 | # modname is set to make c_flags define KBUILD_MODNAME |
75 | modname = $(*F) | 75 | modname = $(notdir $(@:.mod.o=)) |
76 | 76 | ||
77 | quiet_cmd_cc_o_c = CC $@ | 77 | quiet_cmd_cc_o_c = CC $@ |
78 | cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE) \ | 78 | cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE) \ |
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c index be0200e9cdaf..79886413b6d5 100644 --- a/scripts/kconfig/lxdialog/checklist.c +++ b/scripts/kconfig/lxdialog/checklist.c | |||
@@ -187,9 +187,12 @@ int dialog_checklist(const char *title, const char *prompt, int height, | |||
187 | 187 | ||
188 | /* Print the list */ | 188 | /* Print the list */ |
189 | for (i = 0; i < max_choice; i++) { | 189 | for (i = 0; i < max_choice; i++) { |
190 | print_item(list, items[(scroll + i) * 3 + 1], | 190 | if (i != choice) |
191 | status[i + scroll], i, i == choice); | 191 | print_item(list, items[(scroll + i) * 3 + 1], |
192 | status[i + scroll], i, 0); | ||
192 | } | 193 | } |
194 | print_item(list, items[(scroll + choice) * 3 + 1], | ||
195 | status[choice + scroll], choice, 1); | ||
193 | 196 | ||
194 | print_arrows(dialog, choice, item_no, scroll, | 197 | print_arrows(dialog, choice, item_no, scroll, |
195 | box_y, box_x + check_x + 5, list_height); | 198 | box_y, box_x + check_x + 5, list_height); |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 00e21297aefe..f9460a6218de 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
@@ -1056,7 +1056,8 @@ sub output_struct_man(%) { | |||
1056 | # pointer-to-function | 1056 | # pointer-to-function |
1057 | print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n"; | 1057 | print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n"; |
1058 | } elsif ($type =~ m/^(.*?)\s*(:.*)/) { | 1058 | } elsif ($type =~ m/^(.*?)\s*(:.*)/) { |
1059 | print ".BI \" ".$1."\" ".$parameter.$2." \""."\"\n;\n"; | 1059 | # bitfield |
1060 | print ".BI \" ".$1."\ \" ".$parameter.$2." \""."\"\n;\n"; | ||
1060 | } else { | 1061 | } else { |
1061 | $type =~ s/([^\*])$/$1 /; | 1062 | $type =~ s/([^\*])$/$1 /; |
1062 | print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n"; | 1063 | print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n"; |
@@ -1118,7 +1119,10 @@ sub output_function_text(%) { | |||
1118 | my %args = %{$_[0]}; | 1119 | my %args = %{$_[0]}; |
1119 | my ($parameter, $section); | 1120 | my ($parameter, $section); |
1120 | 1121 | ||
1121 | print "Function:\n\n"; | 1122 | print "Name:\n\n"; |
1123 | print $args{'function'}." - ".$args{'purpose'}."\n"; | ||
1124 | |||
1125 | print "\nSynopsis:\n\n"; | ||
1122 | my $start=$args{'functiontype'}." ".$args{'function'}." ("; | 1126 | my $start=$args{'functiontype'}." ".$args{'function'}." ("; |
1123 | print $start; | 1127 | print $start; |
1124 | my $count = 0; | 1128 | my $count = 0; |
@@ -1169,6 +1173,7 @@ sub output_enum_text(%) { | |||
1169 | my $count; | 1173 | my $count; |
1170 | print "Enum:\n\n"; | 1174 | print "Enum:\n\n"; |
1171 | 1175 | ||
1176 | print "enum ".$args{'enum'}." - ".$args{'purpose'}."\n\n"; | ||
1172 | print "enum ".$args{'enum'}." {\n"; | 1177 | print "enum ".$args{'enum'}." {\n"; |
1173 | $count = 0; | 1178 | $count = 0; |
1174 | foreach $parameter (@{$args{'parameterlist'}}) { | 1179 | foreach $parameter (@{$args{'parameterlist'}}) { |
@@ -1197,7 +1202,7 @@ sub output_typedef_text(%) { | |||
1197 | my $count; | 1202 | my $count; |
1198 | print "Typedef:\n\n"; | 1203 | print "Typedef:\n\n"; |
1199 | 1204 | ||
1200 | print "typedef ".$args{'typedef'}."\n"; | 1205 | print "typedef ".$args{'typedef'}." - ".$args{'purpose'}."\n"; |
1201 | output_section_text(@_); | 1206 | output_section_text(@_); |
1202 | } | 1207 | } |
1203 | 1208 | ||
@@ -1206,7 +1211,7 @@ sub output_struct_text(%) { | |||
1206 | my %args = %{$_[0]}; | 1211 | my %args = %{$_[0]}; |
1207 | my ($parameter); | 1212 | my ($parameter); |
1208 | 1213 | ||
1209 | print $args{'type'}." ".$args{'struct'}.":\n\n"; | 1214 | print $args{'type'}." ".$args{'struct'}." - ".$args{'purpose'}."\n\n"; |
1210 | print $args{'type'}." ".$args{'struct'}." {\n"; | 1215 | print $args{'type'}." ".$args{'struct'}." {\n"; |
1211 | foreach $parameter (@{$args{'parameterlist'}}) { | 1216 | foreach $parameter (@{$args{'parameterlist'}}) { |
1212 | if ($parameter =~ /^#/) { | 1217 | if ($parameter =~ /^#/) { |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 0dd16177642d..dfde0e87a765 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -24,7 +24,10 @@ static int all_versions = 0; | |||
24 | /* If we are modposting external module set to 1 */ | 24 | /* If we are modposting external module set to 1 */ |
25 | static int external_module = 0; | 25 | static int external_module = 0; |
26 | /* How a symbol is exported */ | 26 | /* How a symbol is exported */ |
27 | enum export {export_plain, export_gpl, export_gpl_future, export_unknown}; | 27 | enum export { |
28 | export_plain, export_unused, export_gpl, | ||
29 | export_unused_gpl, export_gpl_future, export_unknown | ||
30 | }; | ||
28 | 31 | ||
29 | void fatal(const char *fmt, ...) | 32 | void fatal(const char *fmt, ...) |
30 | { | 33 | { |
@@ -191,7 +194,9 @@ static struct { | |||
191 | enum export export; | 194 | enum export export; |
192 | } export_list[] = { | 195 | } export_list[] = { |
193 | { .str = "EXPORT_SYMBOL", .export = export_plain }, | 196 | { .str = "EXPORT_SYMBOL", .export = export_plain }, |
197 | { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, | ||
194 | { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, | 198 | { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, |
199 | { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, | ||
195 | { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, | 200 | { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, |
196 | { .str = "(unknown)", .export = export_unknown }, | 201 | { .str = "(unknown)", .export = export_unknown }, |
197 | }; | 202 | }; |
@@ -205,6 +210,8 @@ static const char *export_str(enum export ex) | |||
205 | static enum export export_no(const char * s) | 210 | static enum export export_no(const char * s) |
206 | { | 211 | { |
207 | int i; | 212 | int i; |
213 | if (!s) | ||
214 | return export_unknown; | ||
208 | for (i = 0; export_list[i].export != export_unknown; i++) { | 215 | for (i = 0; export_list[i].export != export_unknown; i++) { |
209 | if (strcmp(export_list[i].str, s) == 0) | 216 | if (strcmp(export_list[i].str, s) == 0) |
210 | return export_list[i].export; | 217 | return export_list[i].export; |
@@ -216,8 +223,12 @@ static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) | |||
216 | { | 223 | { |
217 | if (sec == elf->export_sec) | 224 | if (sec == elf->export_sec) |
218 | return export_plain; | 225 | return export_plain; |
226 | else if (sec == elf->export_unused_sec) | ||
227 | return export_unused; | ||
219 | else if (sec == elf->export_gpl_sec) | 228 | else if (sec == elf->export_gpl_sec) |
220 | return export_gpl; | 229 | return export_gpl; |
230 | else if (sec == elf->export_unused_gpl_sec) | ||
231 | return export_unused_gpl; | ||
221 | else if (sec == elf->export_gpl_future_sec) | 232 | else if (sec == elf->export_gpl_future_sec) |
222 | return export_gpl_future; | 233 | return export_gpl_future; |
223 | else | 234 | else |
@@ -366,8 +377,12 @@ static void parse_elf(struct elf_info *info, const char *filename) | |||
366 | info->modinfo_len = sechdrs[i].sh_size; | 377 | info->modinfo_len = sechdrs[i].sh_size; |
367 | } else if (strcmp(secname, "__ksymtab") == 0) | 378 | } else if (strcmp(secname, "__ksymtab") == 0) |
368 | info->export_sec = i; | 379 | info->export_sec = i; |
380 | else if (strcmp(secname, "__ksymtab_unused") == 0) | ||
381 | info->export_unused_sec = i; | ||
369 | else if (strcmp(secname, "__ksymtab_gpl") == 0) | 382 | else if (strcmp(secname, "__ksymtab_gpl") == 0) |
370 | info->export_gpl_sec = i; | 383 | info->export_gpl_sec = i; |
384 | else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) | ||
385 | info->export_unused_gpl_sec = i; | ||
371 | else if (strcmp(secname, "__ksymtab_gpl_future") == 0) | 386 | else if (strcmp(secname, "__ksymtab_gpl_future") == 0) |
372 | info->export_gpl_future_sec = i; | 387 | info->export_gpl_future_sec = i; |
373 | 388 | ||
@@ -1085,38 +1100,64 @@ void buf_write(struct buffer *buf, const char *s, int len) | |||
1085 | buf->pos += len; | 1100 | buf->pos += len; |
1086 | } | 1101 | } |
1087 | 1102 | ||
1088 | void check_license(struct module *mod) | 1103 | static void check_for_gpl_usage(enum export exp, const char *m, const char *s) |
1104 | { | ||
1105 | const char *e = is_vmlinux(m) ?"":".ko"; | ||
1106 | |||
1107 | switch (exp) { | ||
1108 | case export_gpl: | ||
1109 | fatal("modpost: GPL-incompatible module %s%s " | ||
1110 | "uses GPL-only symbol '%s'\n", m, e, s); | ||
1111 | break; | ||
1112 | case export_unused_gpl: | ||
1113 | fatal("modpost: GPL-incompatible module %s%s " | ||
1114 | "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s); | ||
1115 | break; | ||
1116 | case export_gpl_future: | ||
1117 | warn("modpost: GPL-incompatible module %s%s " | ||
1118 | "uses future GPL-only symbol '%s'\n", m, e, s); | ||
1119 | break; | ||
1120 | case export_plain: | ||
1121 | case export_unused: | ||
1122 | case export_unknown: | ||
1123 | /* ignore */ | ||
1124 | break; | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | static void check_for_unused(enum export exp, const char* m, const char* s) | ||
1129 | { | ||
1130 | const char *e = is_vmlinux(m) ?"":".ko"; | ||
1131 | |||
1132 | switch (exp) { | ||
1133 | case export_unused: | ||
1134 | case export_unused_gpl: | ||
1135 | warn("modpost: module %s%s " | ||
1136 | "uses symbol '%s' marked UNUSED\n", m, e, s); | ||
1137 | break; | ||
1138 | default: | ||
1139 | /* ignore */ | ||
1140 | break; | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | static void check_exports(struct module *mod) | ||
1089 | { | 1145 | { |
1090 | struct symbol *s, *exp; | 1146 | struct symbol *s, *exp; |
1091 | 1147 | ||
1092 | for (s = mod->unres; s; s = s->next) { | 1148 | for (s = mod->unres; s; s = s->next) { |
1093 | const char *basename; | 1149 | const char *basename; |
1094 | if (mod->gpl_compatible == 1) { | ||
1095 | /* GPL-compatible modules may use all symbols */ | ||
1096 | continue; | ||
1097 | } | ||
1098 | exp = find_symbol(s->name); | 1150 | exp = find_symbol(s->name); |
1099 | if (!exp || exp->module == mod) | 1151 | if (!exp || exp->module == mod) |
1100 | continue; | 1152 | continue; |
1101 | basename = strrchr(mod->name, '/'); | 1153 | basename = strrchr(mod->name, '/'); |
1102 | if (basename) | 1154 | if (basename) |
1103 | basename++; | 1155 | basename++; |
1104 | switch (exp->export) { | 1156 | else |
1105 | case export_gpl: | 1157 | basename = mod->name; |
1106 | fatal("modpost: GPL-incompatible module %s " | 1158 | if (!mod->gpl_compatible) |
1107 | "uses GPL-only symbol '%s'\n", | 1159 | check_for_gpl_usage(exp->export, basename, exp->name); |
1108 | basename ? basename : mod->name, | 1160 | check_for_unused(exp->export, basename, exp->name); |
1109 | exp->name); | ||
1110 | break; | ||
1111 | case export_gpl_future: | ||
1112 | warn("modpost: GPL-incompatible module %s " | ||
1113 | "uses future GPL-only symbol '%s'\n", | ||
1114 | basename ? basename : mod->name, | ||
1115 | exp->name); | ||
1116 | break; | ||
1117 | case export_plain: /* ignore */ break; | ||
1118 | case export_unknown: /* ignore */ break; | ||
1119 | } | ||
1120 | } | 1161 | } |
1121 | } | 1162 | } |
1122 | 1163 | ||
@@ -1271,7 +1312,7 @@ static void write_if_changed(struct buffer *b, const char *fname) | |||
1271 | } | 1312 | } |
1272 | 1313 | ||
1273 | /* parse Module.symvers file. line format: | 1314 | /* parse Module.symvers file. line format: |
1274 | * 0x12345678<tab>symbol<tab>module[<tab>export] | 1315 | * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something] |
1275 | **/ | 1316 | **/ |
1276 | static void read_dump(const char *fname, unsigned int kernel) | 1317 | static void read_dump(const char *fname, unsigned int kernel) |
1277 | { | 1318 | { |
@@ -1284,7 +1325,7 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
1284 | return; | 1325 | return; |
1285 | 1326 | ||
1286 | while ((line = get_next_line(&pos, file, size))) { | 1327 | while ((line = get_next_line(&pos, file, size))) { |
1287 | char *symname, *modname, *d, *export; | 1328 | char *symname, *modname, *d, *export, *end; |
1288 | unsigned int crc; | 1329 | unsigned int crc; |
1289 | struct module *mod; | 1330 | struct module *mod; |
1290 | struct symbol *s; | 1331 | struct symbol *s; |
@@ -1297,7 +1338,8 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
1297 | *modname++ = '\0'; | 1338 | *modname++ = '\0'; |
1298 | if ((export = strchr(modname, '\t')) != NULL) | 1339 | if ((export = strchr(modname, '\t')) != NULL) |
1299 | *export++ = '\0'; | 1340 | *export++ = '\0'; |
1300 | 1341 | if (export && ((end = strchr(export, '\t')) != NULL)) | |
1342 | *end = '\0'; | ||
1301 | crc = strtoul(line, &d, 16); | 1343 | crc = strtoul(line, &d, 16); |
1302 | if (*symname == '\0' || *modname == '\0' || *d != '\0') | 1344 | if (*symname == '\0' || *modname == '\0' || *d != '\0') |
1303 | goto fail; | 1345 | goto fail; |
@@ -1396,7 +1438,7 @@ int main(int argc, char **argv) | |||
1396 | for (mod = modules; mod; mod = mod->next) { | 1438 | for (mod = modules; mod; mod = mod->next) { |
1397 | if (mod->skip) | 1439 | if (mod->skip) |
1398 | continue; | 1440 | continue; |
1399 | check_license(mod); | 1441 | check_exports(mod); |
1400 | } | 1442 | } |
1401 | 1443 | ||
1402 | for (mod = modules; mod; mod = mod->next) { | 1444 | for (mod = modules; mod; mod = mod->next) { |
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 2b00c6062844..d398c61e55ef 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
@@ -117,7 +117,9 @@ struct elf_info { | |||
117 | Elf_Sym *symtab_start; | 117 | Elf_Sym *symtab_start; |
118 | Elf_Sym *symtab_stop; | 118 | Elf_Sym *symtab_stop; |
119 | Elf_Section export_sec; | 119 | Elf_Section export_sec; |
120 | Elf_Section export_unused_sec; | ||
120 | Elf_Section export_gpl_sec; | 121 | Elf_Section export_gpl_sec; |
122 | Elf_Section export_unused_gpl_sec; | ||
121 | Elf_Section export_gpl_future_sec; | 123 | Elf_Section export_gpl_future_sec; |
122 | const char *strtab; | 124 | const char *strtab; |
123 | char *modinfo; | 125 | char *modinfo; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index e9548bc049e1..d2e80e62ff0c 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1845,15 +1845,20 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
1845 | return -ENOTSUPP; | 1845 | return -ENOTSUPP; |
1846 | 1846 | ||
1847 | switch (field) { | 1847 | switch (field) { |
1848 | case AUDIT_SE_USER: | 1848 | case AUDIT_SUBJ_USER: |
1849 | case AUDIT_SE_ROLE: | 1849 | case AUDIT_SUBJ_ROLE: |
1850 | case AUDIT_SE_TYPE: | 1850 | case AUDIT_SUBJ_TYPE: |
1851 | case AUDIT_OBJ_USER: | ||
1852 | case AUDIT_OBJ_ROLE: | ||
1853 | case AUDIT_OBJ_TYPE: | ||
1851 | /* only 'equals' and 'not equals' fit user, role, and type */ | 1854 | /* only 'equals' and 'not equals' fit user, role, and type */ |
1852 | if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) | 1855 | if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) |
1853 | return -EINVAL; | 1856 | return -EINVAL; |
1854 | break; | 1857 | break; |
1855 | case AUDIT_SE_SEN: | 1858 | case AUDIT_SUBJ_SEN: |
1856 | case AUDIT_SE_CLR: | 1859 | case AUDIT_SUBJ_CLR: |
1860 | case AUDIT_OBJ_LEV_LOW: | ||
1861 | case AUDIT_OBJ_LEV_HIGH: | ||
1857 | /* we do not allow a range, indicated by the presense of '-' */ | 1862 | /* we do not allow a range, indicated by the presense of '-' */ |
1858 | if (strchr(rulestr, '-')) | 1863 | if (strchr(rulestr, '-')) |
1859 | return -EINVAL; | 1864 | return -EINVAL; |
@@ -1874,29 +1879,34 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
1874 | tmprule->au_seqno = latest_granting; | 1879 | tmprule->au_seqno = latest_granting; |
1875 | 1880 | ||
1876 | switch (field) { | 1881 | switch (field) { |
1877 | case AUDIT_SE_USER: | 1882 | case AUDIT_SUBJ_USER: |
1883 | case AUDIT_OBJ_USER: | ||
1878 | userdatum = hashtab_search(policydb.p_users.table, rulestr); | 1884 | userdatum = hashtab_search(policydb.p_users.table, rulestr); |
1879 | if (!userdatum) | 1885 | if (!userdatum) |
1880 | rc = -EINVAL; | 1886 | rc = -EINVAL; |
1881 | else | 1887 | else |
1882 | tmprule->au_ctxt.user = userdatum->value; | 1888 | tmprule->au_ctxt.user = userdatum->value; |
1883 | break; | 1889 | break; |
1884 | case AUDIT_SE_ROLE: | 1890 | case AUDIT_SUBJ_ROLE: |
1891 | case AUDIT_OBJ_ROLE: | ||
1885 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); | 1892 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); |
1886 | if (!roledatum) | 1893 | if (!roledatum) |
1887 | rc = -EINVAL; | 1894 | rc = -EINVAL; |
1888 | else | 1895 | else |
1889 | tmprule->au_ctxt.role = roledatum->value; | 1896 | tmprule->au_ctxt.role = roledatum->value; |
1890 | break; | 1897 | break; |
1891 | case AUDIT_SE_TYPE: | 1898 | case AUDIT_SUBJ_TYPE: |
1899 | case AUDIT_OBJ_TYPE: | ||
1892 | typedatum = hashtab_search(policydb.p_types.table, rulestr); | 1900 | typedatum = hashtab_search(policydb.p_types.table, rulestr); |
1893 | if (!typedatum) | 1901 | if (!typedatum) |
1894 | rc = -EINVAL; | 1902 | rc = -EINVAL; |
1895 | else | 1903 | else |
1896 | tmprule->au_ctxt.type = typedatum->value; | 1904 | tmprule->au_ctxt.type = typedatum->value; |
1897 | break; | 1905 | break; |
1898 | case AUDIT_SE_SEN: | 1906 | case AUDIT_SUBJ_SEN: |
1899 | case AUDIT_SE_CLR: | 1907 | case AUDIT_SUBJ_CLR: |
1908 | case AUDIT_OBJ_LEV_LOW: | ||
1909 | case AUDIT_OBJ_LEV_HIGH: | ||
1900 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); | 1910 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); |
1901 | break; | 1911 | break; |
1902 | } | 1912 | } |
@@ -1948,7 +1958,8 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1948 | /* a field/op pair that is not caught here will simply fall through | 1958 | /* a field/op pair that is not caught here will simply fall through |
1949 | without a match */ | 1959 | without a match */ |
1950 | switch (field) { | 1960 | switch (field) { |
1951 | case AUDIT_SE_USER: | 1961 | case AUDIT_SUBJ_USER: |
1962 | case AUDIT_OBJ_USER: | ||
1952 | switch (op) { | 1963 | switch (op) { |
1953 | case AUDIT_EQUAL: | 1964 | case AUDIT_EQUAL: |
1954 | match = (ctxt->user == rule->au_ctxt.user); | 1965 | match = (ctxt->user == rule->au_ctxt.user); |
@@ -1958,7 +1969,8 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1958 | break; | 1969 | break; |
1959 | } | 1970 | } |
1960 | break; | 1971 | break; |
1961 | case AUDIT_SE_ROLE: | 1972 | case AUDIT_SUBJ_ROLE: |
1973 | case AUDIT_OBJ_ROLE: | ||
1962 | switch (op) { | 1974 | switch (op) { |
1963 | case AUDIT_EQUAL: | 1975 | case AUDIT_EQUAL: |
1964 | match = (ctxt->role == rule->au_ctxt.role); | 1976 | match = (ctxt->role == rule->au_ctxt.role); |
@@ -1968,7 +1980,8 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1968 | break; | 1980 | break; |
1969 | } | 1981 | } |
1970 | break; | 1982 | break; |
1971 | case AUDIT_SE_TYPE: | 1983 | case AUDIT_SUBJ_TYPE: |
1984 | case AUDIT_OBJ_TYPE: | ||
1972 | switch (op) { | 1985 | switch (op) { |
1973 | case AUDIT_EQUAL: | 1986 | case AUDIT_EQUAL: |
1974 | match = (ctxt->type == rule->au_ctxt.type); | 1987 | match = (ctxt->type == rule->au_ctxt.type); |
@@ -1978,9 +1991,12 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
1978 | break; | 1991 | break; |
1979 | } | 1992 | } |
1980 | break; | 1993 | break; |
1981 | case AUDIT_SE_SEN: | 1994 | case AUDIT_SUBJ_SEN: |
1982 | case AUDIT_SE_CLR: | 1995 | case AUDIT_SUBJ_CLR: |
1983 | level = (field == AUDIT_SE_SEN ? | 1996 | case AUDIT_OBJ_LEV_LOW: |
1997 | case AUDIT_OBJ_LEV_HIGH: | ||
1998 | level = ((field == AUDIT_SUBJ_SEN || | ||
1999 | field == AUDIT_OBJ_LEV_LOW) ? | ||
1984 | &ctxt->range.level[0] : &ctxt->range.level[1]); | 2000 | &ctxt->range.level[0] : &ctxt->range.level[1]); |
1985 | switch (op) { | 2001 | switch (op) { |
1986 | case AUDIT_EQUAL: | 2002 | case AUDIT_EQUAL: |